/*
 * Copyright (c) 2018 - 2028. www.vtuzx.com Inc. All Rights Reserved
 */
package com.vtuzx.kingdee.xqc_api.service.impl;

import com.vtuzx.core.VtuzxException;
import com.vtuzx.core.bean.dto.VtuzxMap;
import com.vtuzx.core.bean.dto.VtuzxPage;
import com.vtuzx.core.bean.dto.VtuzxToken;
import com.vtuzx.core.constant.IVtuzxConst;
import com.vtuzx.core.file.excel.VtuzxExcel;
import com.vtuzx.core.file.excel.VtuzxExcelCell;
import com.vtuzx.core.file.excel.VtuzxExcelRow;
import com.vtuzx.core.file.excel.VtuzxExcelSheet;
import com.vtuzx.core.utils.VtuzxUtil;
import com.vtuzx.fast.utils.FastUtil;
import com.vtuzx.kingdee.xqc_api.service.IXqcOtherService;
import com.vtuzx.kingdee.xqc_api.service.IXqcSyncKingdeeOrderService;
import com.vtuzx.kingdee.xqc_core.bean.VtuzxArrayList;
import com.vtuzx.kingdee.xqc_core.bean.kingdee.VtuzxKingdeeCloudClient;
import com.vtuzx.kingdee.xqc_core.dao.*;
import com.vtuzx.kingdee.xqc_core.service.IVtuzxKingdeeService;
import com.vtuzx.web.bean.VtuzxDownloadBean;
import org.apache.poi.hssf.record.PageBreakRecord;
import org.aspectj.weaver.patterns.CflowPointcut;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class XqcSyncKingdeeOrderServiceImpl implements IXqcSyncKingdeeOrderService {

    /**
     * Logger
     */
    private static final Logger _logger = LoggerFactory.getLogger(XqcSyncKingdeeOrderServiceImpl.class);

    /**
     * 金蝶
     */
    @Autowired
    private IVtuzxKingdeeService kingdeeService;

    @Autowired
    private SyncDao syncDao;

    @Autowired
    private XqcOtherServiceImpl otherService;

    /**
     * 金蝶
     */
    @Autowired
    private PurInDao purInDao;

    @Autowired
    private PurReturnDao purReturnDao;

    @Autowired
    private PurReturnDetailDao purReturnDetailDao;

    /**
     * 金蝶
     */
    @Autowired
    private PurInDetailDao purInDetailDao;

    /**
     * 金蝶
     */
    @Autowired
    private OtherInDao otherInDao;

    /**
     * 金蝶
     */
    @Autowired
    private OtherInDetailDao otherInDetailDao;

    /**
     * 金蝶
     */
    @Autowired
    private SyncOrderDao syncOrderDao;

    /**
     * 金蝶
     */
    @Autowired
    private SaleOutDao saleOutDao;

    /**
     * 金蝶
     */
    @Autowired
    private SaleOutDetailDao saleOutDetailDao;

    /**
     * 金蝶
     */
    @Autowired
    private OtherOutDetailDao otherOutDetailDao;

    /**
     * 金蝶
     */
    @Autowired
    private OtherOutDao otherOutDao;

    /**
     * 金蝶
     */
    @Autowired
    private PrdTaskDao prdTaskDao;
    /**
     * 金蝶
     */
    @Autowired
    private PrdTaskDetailDao prdTaskDetailDao;

    @Autowired
    private MDictDao dictDao;

    @Autowired
    private MaterialDao materialDao;

    @Autowired
    private MaterialBomPickDao materialBomPickDao;

    @Autowired
    private MaterialBomPickDetailDao materialBomPickDetailDao;

    @Autowired
    private MaterialBomSupplementDao materialBomSupplementDao;

    @Autowired
    private MaterialBomSupplementDetailDao materialBomSupplementDetailDao;

    @Autowired
    private MaterialBomReturnDetailDao materialBomReturnDetailDao;

    @Autowired
    private MaterialBomReturnDao materialBomReturnDao;

    @Autowired
    private PrdInDetailDao prdInDetailDao;

    @Autowired
    private PrdInDao prdInDao;

    @Autowired
    private PurContractDao purContractDao;

    @Autowired
    private PurContractDetailDao purContractDetailDao;

    @Autowired
    private PurOrderDao purOrderDao;

    @Autowired
    private PurOrderDetailDao purOrderDetailDao;

    @Autowired
    private AllocationDao allocationDao;

    @Autowired
    private AllocationDetailDao allocationDetailDao;

    @Autowired
    private PrdPushRuleDao prdPushRuleDao;

    //区分传货品库与委外库
    //20251014生产成品“委外库”
    /*public static final Set<String> CP_WAREHOUSECODE;
    static {
        Set<String> codeSet_CP_WAREHOUSECODE = new HashSet<>(Arrays.asList("007", "008", "009", "015", "016"));
        CP_WAREHOUSECODE = Collections.unmodifiableSet(codeSet_CP_WAREHOUSECODE);
    }*/

    public static VtuzxMap list2Map(List<? extends Map<String, Object>> dataList, String keyCol) {
        VtuzxMap ret = new VtuzxMap();
        for (Map<String, Object> m : dataList) {
            String key = VtuzxUtil.getString(m, keyCol);
            if (!VtuzxUtil.isEmpty(key)) {
                ret.put(key, m);
            }
        }
        return ret;
    }

    public VtuzxMap getOptions(Map<String, Object> param) {
        List<String> keys = VtuzxUtil.getObject(param, "keys");
        Iterator<Document> dictList = dictDao.findList(Criteria.where("key").in(keys).and("effect").is(true), null, 0, 0);
        VtuzxMap retMap = new VtuzxMap();
        while (dictList.hasNext()) {
            Document dict = dictList.next();
            List<VtuzxMap> options = new ArrayList<>();
            String key = VtuzxUtil.getObject(dict, "key");
            retMap.put(key, options);
            List<Document> dbs = VtuzxUtil.getObject(dict, "details");
            if (dbs != null) {
                sortDictDetails(dbs);
                for (Document detail : dbs) {
                    if (VtuzxUtil.getBoolean(detail, "effect")) {
                        VtuzxMap dictDetail = new VtuzxMap("key", VtuzxUtil.getString(detail, "key"))
                                .append("name", VtuzxUtil.getString(detail, "name"))
                                .append("remark", VtuzxUtil.getString(detail, "remark"));
                        options.add(dictDetail);
                    }
                }
            }
        }
        return retMap;
    }

    private void sortDictDetails(List<Document> details) {
        details.sort((o1, o2) -> {
            int sort1 = VtuzxUtil.getInt(o1, "sort");
            String key1 = VtuzxUtil.getString(o1, "key");
            int sort2 = VtuzxUtil.getInt(o2, "sort");
            String key2 = VtuzxUtil.getString(o2, "key");
            return sort1 == sort2 ? key1.compareTo(key2) : sort1 - sort2;
        });
    }


    @Override
    public void syncPurInOrder(ObjectId userId, String name, String billNo, String source) throws Exception {

        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        boolean success = VtuzxUtil.getBoolean(historyDoc, "success");
//        if (success) {
//            return;
//        }
        Document purInOrderDoc = purInDao.findOne(Criteria.where("billNo").is(billNo));

        historyDoc.append("billNo", billNo);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("source", source);
        historyDoc.append("data", purInOrderDoc);
        historyDoc.append("event", "purInStock");
        try {
            syncPurInOrderInner(historyDoc);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("purInOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    @Override
    public void syncPurInOrderBn(ObjectId userId, String name, String billNo, String source) throws Exception {
        // 根据billNo查询历史文档
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        // 如果历史文档为空，则创建一个新的历史文档
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            // 否则获取历史文档的_id
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        // 获取历史文档的success字段
        boolean success = VtuzxUtil.getBoolean(historyDoc, "success");
        // 根据billNo查询purInOrder文档
        Document purInOrderDoc = purInDao.findOne(Criteria.where("billNo").is(billNo));
        // 将billNo、userId、userName、source、purInOrderDoc、event字段添加到历史文档中
        historyDoc.append("billNo", billNo);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("source", source);
        historyDoc.append("data", purInOrderDoc);
        historyDoc.append("event", "purInStock");
        try {
            // 调用syncPurInOrderInnerBn方法
            syncPurInOrderInnerBn(historyDoc);
            // 将success字段设置为true
            historyDoc.append("success", true);
            // 如果历史文档的_id为空，则插入历史文档
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                // 否则，移除_id、createTime、updateTime、message字段，添加updateUserId、updateUserName字段，更新历史文档
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            // 将purInOrder、message、success字段添加到历史文档中，并抛出异常
            historyDoc.append("purInOrder", false).append("message", e.getMessage()).append("success", false);
            // 如果历史文档的_id为空，则插入历史文档
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                // 否则，移除_id、createTime、updateTime字段，更新历史文档
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    private void syncPurInOrderInner(Document historyDoc) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");

        Document purIn = VtuzxUtil.getObject(historyDoc, "data");
        String createUserName = VtuzxUtil.getString(purIn, "createUserName");
//        String supplierNo = VtuzxUtil.getString(purIn, "supplierNo");
        String auditUserName = VtuzxUtil.getString(purIn, "auditUserName");
        Date createTime = VtuzxUtil.getObject(purIn, "createTime");
//        String supplier = "";
//        if (!supplierNo.startsWith("0")) {
//            List<VtuzxMap> supplierQuery = kingdeeService.query(client, "BD_Supplier", new VtuzxArrayList<>(
//                            "Fnumber_Y",
//                            "FNumber"
//                    ),
//                    String.format("Fnumber_Y = '%s'", supplierNo), null, 0, 1);
//            if (VtuzxUtil.isEmpty(supplierQuery)) {
//                throw new VtuzxException(String.format("供应商[%s]在金蝶中不存在", supplierNo));
//            }
//            supplier = VtuzxUtil.getString(supplierQuery.get(0), "FNumber");
//        } else {
//            supplier = supplierNo;
//        }
        //查询金蝶供应商


        List<VtuzxMap> materialList = new ArrayList<>();

        List<String> materialNoList = new ArrayList<>();
        Iterator<Document> purInItr = purInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (purInItr.hasNext()) {
            Document purInDoc = purInItr.next();
            VtuzxMap purInMap = new VtuzxMap(purInDoc);
            String materialNumber = VtuzxUtil.getString(purInMap, "materialNo");
            materialNoList.add(materialNumber);
            materialList.add(purInMap);
        }

        String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
        List<VtuzxMap> materialQuery = kingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
                        "FIsBatchManage",
                        "FNumber"
                ),
                String.format("FNumber  in (%s)", materialNoCond), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialQuery)) return;

        VtuzxMap materialMap = new VtuzxMap();
        for (VtuzxMap material : materialQuery) {
            String number = VtuzxUtil.getString(material, "FNumber");
            boolean isBatchManage = VtuzxUtil.getBoolean(material, "FIsBatchManage");
            materialMap.append(number, isBatchManage);
        }

        String number = "";
        for (Map<String, Object> material : materialList) {
            String supplier = "";
            Map<String, Object> inStockParam = new LinkedHashMap<>();
            inStockParam.put("NeedUpDateFields", new ArrayList<>());
            inStockParam.put("NeedReturnFields", new ArrayList<>());
            inStockParam.put("IsDeleteEntry", true);
            inStockParam.put("SubSystemId", "");
            inStockParam.put("IsVerifyBaseDataField", false);
            inStockParam.put("IsEntryBatchFill", true);
            inStockParam.put("ValidateFlag", true);
            inStockParam.put("NumberSearch", true);
            inStockParam.put("InterationFlags", "");

            Map<String, Object> inStockModel = new LinkedHashMap<>();

            List<Map<String, Object>> fInStockEntry = new ArrayList<>();
            String supplierNo = VtuzxUtil.getString(material, "supplierNo");

            if (!supplierNo.startsWith("0")) {
                List<VtuzxMap> supplierQuery = kingdeeService.query(client, "BD_Supplier", new VtuzxArrayList<>(
//                                "Fnumber_Y",
                                "FNumber"
                        ),
                        String.format("Fnumber = '%s'", supplierNo), null, 0, 1);
                if (VtuzxUtil.isEmpty(supplierQuery)) {
                    throw new VtuzxException(String.format("供应商[%s]在金蝶中不存在", supplierNo));
                }
                supplier = VtuzxUtil.getString(supplierQuery.get(0), "FNumber");
            } else {
                supplier = supplierNo;
            }

            String materialNo = VtuzxUtil.getString(material, "materialNo");
            //查询一下税率
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            String fTaxRateName = VtuzxUtil.getString(materialDoc, "fTaxRateName");

            String substring = fTaxRateName.substring(0, fTaxRateName.indexOf("%"));
            boolean isBatchManage = VtuzxUtil.getBoolean(materialMap, materialNo);
            String batchNo = VtuzxUtil.getString(material, "batchNo");
            //批次是BN开头的不传金蝶
//            if (batchNo.startsWith("BN")) {
//                continue;
//            }
            String stockNo = VtuzxUtil.getString(material, "stockNo");
            String unit = VtuzxUtil.getString(material, "unit");
            double count = Math.abs(VtuzxUtil.getDouble(material, "count"));

            Map<String, Object> detailMap = new LinkedHashMap<>();

//            detailMap.put("FEntryId",0);
            detailMap.put("FRowType", "Standard");
            detailMap.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
            detailMap.put("FUnitID", new VtuzxMap("FNumber", unit));
            detailMap.put("FRealQty", count);
            detailMap.put("FPriceUnitID", new VtuzxMap("FNumber", unit));
            if (isBatchManage) {
                detailMap.put("FLot", new VtuzxMap("FNumber", batchNo));
            }
            detailMap.put("FStockId", new VtuzxMap("FNumber", stockNo));
            detailMap.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
            detailMap.put("FGiveAway", false);
            detailMap.put("FOWNERTYPEID", "BD_OwnerOrg");//货主类型
            detailMap.put("FCheckInComing", false);
            detailMap.put("FIsReceiveUpdateStock", false);
            detailMap.put("FPriceBaseQty", count);
            detailMap.put("FRemainInStockUnitId", new VtuzxMap("FNumber", unit));
            detailMap.put("FBILLINGCLOSE", false);
            detailMap.put("FRemainInStockQty", count);
            detailMap.put("FAPNotJoinQty", count);
            detailMap.put("FRemainInStockBaseQty", count);
            detailMap.put("FEntryTaxRate", substring);

            detailMap.put("FOWNERID", new Document("FNumber", "100"));
            fInStockEntry.add(detailMap);
            Map<String, Object> fInStockFin = new LinkedHashMap<>();//财务信息
            fInStockFin.put("FSettleOrgId", new Document("FNumber", "100"));
            fInStockFin.put("FSettleCurrId", new Document("FNumber", "PRE001"));
            fInStockFin.put("FIsIncludedTax", true);
            fInStockFin.put("FPriceTimePoint", "1");
            fInStockFin.put("FLocalCurrId", new Document("FNumber", "PRE001"));
            fInStockFin.put("FExchangeTypeId", new Document("FNumber", "HLTX01_SYS"));
            fInStockFin.put("FExchangeRate", 1.0);
            fInStockFin.put("FISPRICEEXCLUDETAX", true);
            inStockModel.put("FID", 0);
            inStockModel.put("FBillTypeID", new Document("FNumber", "RKD01_SYS"));
            inStockModel.put("FDate", VtuzxUtil.formatYmdHmsF(createTime));
//            inStockModel.put("FDate", "2025-10-31 00:00:00");
            inStockModel.put("FStockOrgId", new Document("FNumber", "100"));
            inStockModel.put("FDemandOrgId", new Document("FNumber", "100"));
            inStockModel.put("FPurchaseOrgId", new Document("FNumber", "100"));
            inStockModel.put("FSupplierId", new VtuzxMap("FNumber", supplier));
            inStockModel.put("FSupplyId", new VtuzxMap("FNumber", supplier));
            inStockModel.put("FSettleId", new VtuzxMap("FNumber", supplier));
            inStockModel.put("FChargeId", new VtuzxMap("FNumber", supplier));
            inStockModel.put("FOwnerTypeIdHead", "BD_OwnerOrg");
            inStockModel.put("FOwnerIdHead", new Document("FNumber", "100"));
            inStockModel.put("FSplitBillType", "A");
            inStockModel.put("F_ora_ZTDJH", billNo);
            inStockModel.put("F_ora_CZRY", createUserName);
            inStockModel.put("F_ora_FHR", auditUserName);
            inStockModel.put("F_ora_SJLY", source);
            inStockModel.put("F_ora_ZTYWRQ", createTime);
            inStockModel.put("FInStockFin", fInStockFin);
            inStockModel.put("FInStockEntry", fInStockEntry);


            inStockParam.put("Model", inStockModel);
            historyDoc.append("param", new VtuzxMap("STK_InStock", inStockParam));
            List<VtuzxMap> stkInStockList = kingdeeService.save(client, "STK_InStock", inStockParam);
            VtuzxMap stkInStockMap = stkInStockList.get(0);
            number = VtuzxUtil.getString(stkInStockMap, "Number");
            kingdeeService.submit(client, "STK_InStock", "0", number);
            kingdeeService.audit(client, "STK_InStock", "0", number, "STK_InvCheckResult");

            historyDoc.append("kingdeeNumber", number);
            historyDoc.append("purInOrder", true);
        }
    }

    private void syncPurInOrderInnerBn(Document historyDoc) throws Exception {
        // 登录金蝶系统
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdeeYX();
        // 从历史文档中获取订单号
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        // 从历史文档中获取来源
        String source = VtuzxUtil.getString(historyDoc, "source");
        // 从历史文档中获取采购入库单
        Document purIn = VtuzxUtil.getObject(historyDoc, "data");
        // 从采购入库单中获取创建人
        String createUserName = VtuzxUtil.getString(purIn, "createUserName");
        // 从采购入库单中获取审核人
        String auditUserName = VtuzxUtil.getString(purIn, "auditUserName");
        // 从采购入库单中获取创建时间
        Date createTime = VtuzxUtil.getObject(purIn, "createTime");
        // 创建一个空的物料列表
        List<VtuzxMap> materialList = new ArrayList<>();
        // 创建一个空的物料号列表
        List<String> materialNoList = new ArrayList<>();
        // 从采购入库单明细表中查找订单号为billNo的数据
        Iterator<Document> purInItr = purInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        // 遍历purInItr
        while (purInItr.hasNext()) {
            // 获取purInItr中的下一个元素
            Document purInDoc = purInItr.next();
            // 将purInDoc转换为VtuzxMap
            VtuzxMap purInMap = new VtuzxMap(purInDoc);
            // 从purInMap中获取materialNo字段的值
            String materialNumber = VtuzxUtil.getString(purInMap, "materialNo");
            // 将materialNumber添加到materialNoList中
            materialNoList.add(materialNumber);
            // 将purInMap添加到materialList中
            materialList.add(purInMap);
        }
        // 将materialNoList转换成字符串，用逗号分隔，并且给每个元素加上单引号
        String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
        // 根据materialNoCond查询BD_MATERIAL表中的FIsBatchManage和FNumber字段
        List<VtuzxMap> materialQuery = kingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
                        "FIsBatchManage",
                        "FNumber"
                ),
                String.format("FNumber  in (%s)", materialNoCond), null, 0, 0);
        // 如果查询结果为空，则返回
        if (VtuzxUtil.isEmpty(materialQuery)) return;
        // 创建一个VtuzxMap对象，用于存储查询结果
        VtuzxMap materialMap = new VtuzxMap();
        // 遍历查询结果
        for (VtuzxMap material : materialQuery) {
            // 获取FNumber字段的值
            String number = VtuzxUtil.getString(material, "FNumber");
            // 获取FIsBatchManage字段的值
            boolean isBatchManage = VtuzxUtil.getBoolean(material, "FIsBatchManage");
            // 将FNumber和FIsBatchManage的值存入materialMap对象中
            materialMap.append(number, isBatchManage);
        }
        String number = "";
        // 遍历材料列表
        for (Map<String, Object> material : materialList) {
            // 供应商编号
            String supplier = "";
            // 入库参数
            Map<String, Object> inStockParam = new LinkedHashMap<>();
            // 需要更新的字段
            inStockParam.put("NeedUpDateFields", new ArrayList<>());
            // 需要返回的字段
            inStockParam.put("NeedReturnFields", new ArrayList<>());
            // 是否删除条目
            inStockParam.put("IsDeleteEntry", true);
            // 子系统ID
            inStockParam.put("SubSystemId", "");
            // 是否验证基础数据字段
            inStockParam.put("IsVerifyBaseDataField", false);
            // 是否批量填充
            inStockParam.put("IsEntryBatchFill", true);
            // 验证标志
            inStockParam.put("ValidateFlag", true);
            // 数字搜索
            inStockParam.put("NumberSearch", true);
            // 交互标志
            inStockParam.put("InterationFlags", "");
            // 入库模型
            Map<String, Object> inStockModel = new LinkedHashMap<>();
            // 入库条目
            List<Map<String, Object>> fInStockEntry = new ArrayList<>();
            // 供应商编号
            String supplierNo = VtuzxUtil.getString(material, "supplierNo");
            // 如果供应商编号不是以0开头
            if (!supplierNo.startsWith("0")) {
                // 查询供应商
                List<VtuzxMap> supplierQuery = kingdeeService.query(client, "BD_Supplier", new VtuzxArrayList<>(
                                "FNumber"
                        ),
                        String.format("Fnumber = '%s'", supplierNo), null, 0, 1);
                // 判断供应商查询结果是否为空
                if (VtuzxUtil.isEmpty(supplierQuery)) {
                    // 如果为空，则抛出异常
                    throw new VtuzxException(String.format("供应商[%s]在金蝶中不存在", supplierNo));
                }
                // 获取供应商编号
                supplier = VtuzxUtil.getString(supplierQuery.get(0), "FNumber");
            } else {
                // 如果供应商编号不为空，则直接赋值
                supplier = supplierNo;
            }
            // 获取物料编号
            String materialNo = VtuzxUtil.getString(material, "materialNo");
            // 根据物料编号查询物料信息
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            // 获取税率名称
            String fTaxRateName = VtuzxUtil.getString(materialDoc, "fTaxRateName");
            // 获取税率名称的数字部分
            String substring = fTaxRateName.substring(0, fTaxRateName.indexOf("%"));
            // 判断是否进行批次管理
            boolean isBatchManage = VtuzxUtil.getBoolean(materialMap, materialNo);
            // 获取批次号
            String batchNo = VtuzxUtil.getString(material, "batchNo");
            // 获取库存号
            String stockNo = VtuzxUtil.getString(material, "stockNo");
            // 获取单位
            String unit = VtuzxUtil.getString(material, "unit");
            // 获取数量
            double count = Math.abs(VtuzxUtil.getDouble(material, "count"));
            // 创建一个LinkedHashMap，用于存储明细信息
            Map<String, Object> detailMap = new LinkedHashMap<>();
            // 设置行类型
            detailMap.put("FRowType", "Standard");
            // 设置物料ID
            detailMap.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
            // 设置单位ID
            detailMap.put("FUnitID", new VtuzxMap("FNumber", unit));
            // 设置实际数量
            detailMap.put("FRealQty", count);
            // 设置单价单位ID
            detailMap.put("FPriceUnitID", new VtuzxMap("FNumber", unit));
            // 如果是批量管理，则将批次号放入detailMap中
            if (isBatchManage) {
                detailMap.put("FLot", new VtuzxMap("FNumber", batchNo));
            }
            //向detailMap中添加FStockId键值对，值为VtuzxMap对象，其中FNumber键的值为stockNo
            detailMap.put("FStockId", new VtuzxMap("FNumber", stockNo));
            //向detailMap中添加FStockStatusId键值对，值为VtuzxMap对象，其中FNumber键的值为"KCZT01_SYS"
            detailMap.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
            //向detailMap中添加FGiveAway键值对，值为false
            detailMap.put("FGiveAway", false);
            //向detailMap中添加FOWNERTYPEID键值对，值为"BD_OwnerOrg"
            detailMap.put("FOWNERTYPEID", "BD_OwnerOrg");
            //向detailMap中添加FCheckInComing键值对，值为false
            detailMap.put("FCheckInComing", false);
            //向detailMap中添加FIsReceiveUpdateStock键值对，值为false
            detailMap.put("FIsReceiveUpdateStock", false);
            //向detailMap中添加FPriceBaseQty键值对，值为count
            detailMap.put("FPriceBaseQty", count);
            //向detailMap中添加FRemainInStockUnitId键值对，值为VtuzxMap对象，其中FNumber键的值为unit
            detailMap.put("FRemainInStockUnitId", new VtuzxMap("FNumber", unit));
            //向detailMap中添加FBILLINGCLOSE键值对，值为false
            detailMap.put("FBILLINGCLOSE", false);
            //向detailMap中添加FRemainInStockQty键值对，值为count
            detailMap.put("FRemainInStockQty", count);
            //向detailMap中添加FAPNotJoinQty键值对，值为count
            detailMap.put("FAPNotJoinQty", count);
            //向detailMap中添加FRemainInStockBaseQty键值对，值为count
            detailMap.put("FRemainInStockBaseQty", count);
            //向detailMap中添加FEntryTaxRate键值对，值为substring
            detailMap.put("FEntryTaxRate", substring);
            //向detailMap中添加FOWNERID键值对，值为Document对象，其中FNumber键的值为"100"
            detailMap.put("FOWNERID", new Document("FNumber", "100"));
            //将detailMap添加到fInStockEntry中
            fInStockEntry.add(detailMap);
            // 创建一个LinkedHashMap对象fInStockFin
            Map<String, Object> fInStockFin = new LinkedHashMap<>();
            // 向fInStockFin对象中添加键值对，键为"FSettleOrgId"，值为一个包含"FNumber"键和"100"值的Document对象
            fInStockFin.put("FSettleOrgId", new Document("FNumber", "100"));
            // 向fInStockFin对象中添加键值对，键为"FSettleCurrId"，值为一个包含"FNumber"键和"PRE001"值的Document对象
            fInStockFin.put("FSettleCurrId", new Document("FNumber", "PRE001"));
            // 向fInStockFin对象中添加键值对，键为"FIsIncludedTax"，值为true
            fInStockFin.put("FIsIncludedTax", true);
            // 向fInStockFin对象中添加键值对，键为"FPriceTimePoint"，值为"1"
            fInStockFin.put("FPriceTimePoint", "1");
            // 将"FLocalCurrId"键值对存入fInStockFin中，值为Document对象，其中FNumber的值为"PRE001"
            fInStockFin.put("FLocalCurrId", new Document("FNumber", "PRE001"));
            // 向fInStockFin对象中添加键值对，键为"FLocalCurrId"，值为一个包含"FNumber"键和"PRE001"值的Document对象
            fInStockFin.put("FExchangeTypeId", new Document("FNumber", "HLTX01_SYS"));
            // 向fInStockFin对象中添加键值对，键为"FExchangeTypeId"，值为一个包含"FNumber"键和"HLTX01_SYS"值的Document对象
            fInStockFin.put("FExchangeRate", 1.0);
            // 向fInStockFin对象中添加键值对，键为"FExchangeRate"，值为1.0
            fInStockFin.put("FISPRICEEXCLUDETAX", true);
            // 向fInStockFin对象中添加键值对，键为"FISPRICEEXCLUDETAX"，值为true
            inStockModel.put("FID", 0);
            //向inStockModel中添加FBillTypeID键值对，值为Document对象，其中FNumber键的值为"RKD01_SYS"
            inStockModel.put("FBillTypeID", new Document("FNumber", "RKD01_SYS"));
            //向inStockModel中添加FDate键值对，值为VtuzxUtil.formatYmdHmsF(createTime)的返回值
            inStockModel.put("FDate", VtuzxUtil.formatYmdHmsF(createTime));
            /*20251015===日期*/
            /*inStockModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));*/
            //向inStockModel中添加FStockOrgId键值对，值为Document对象，其中FNumber键的值为"100"
            inStockModel.put("FStockOrgId", new Document("FNumber", "100"));
            //向inStockModel中添加FDemandOrgId键值对，值为Document对象，其中FNumber键的值为"100"
            inStockModel.put("FDemandOrgId", new Document("FNumber", "100"));
            //向inStockModel中添加FPurchaseOrgId键值对，值为Document对象，其中FNumber键的值为"100"
            inStockModel.put("FPurchaseOrgId", new Document("FNumber", "100"));
            //向inStockModel中添加FSupplierId键值对，值为VtuzxMap对象，其中FNumber键的值为supplier
            inStockModel.put("FSupplierId", new VtuzxMap("FNumber", supplier));
            //向inStockModel中添加FSupplyId键值对，值为VtuzxMap对象，其中FNumber键的值为supplier
            inStockModel.put("FSupplyId", new VtuzxMap("FNumber", supplier));
            //向inStockModel中添加FSettleId键值对，值为VtuzxMap对象，其中FNumber键的值为supplier
            inStockModel.put("FSettleId", new VtuzxMap("FNumber", supplier));
            //向inStockModel中添加FChargeId键值对，值为VtuzxMap对象，其中FNumber键的值为supplier
            inStockModel.put("FChargeId", new VtuzxMap("FNumber", supplier));
            //向inStockModel中添加FOwnerTypeIdHead键值对，值为"BD_OwnerOrg"
            inStockModel.put("FOwnerTypeIdHead", "BD_OwnerOrg");
            // 设置入库单表头信息
            inStockModel.put("FOwnerIdHead", new Document("FNumber", "100"));
            inStockModel.put("FSplitBillType", "A");
            inStockModel.put("F_ora_ZTDJH", billNo);
            inStockModel.put("F_ora_CZRY", createUserName);
            inStockModel.put("F_ora_FHR", auditUserName);
            inStockModel.put("F_ora_SJLY", source);
            inStockModel.put("F_ora_ZTYWRQ", createTime);
            inStockModel.put("FInStockFin", fInStockFin);
            inStockModel.put("FInStockEntry", fInStockEntry);
            // 将入库单表头信息放入入库单参数中
            inStockParam.put("Model", inStockModel);
            // 将入库单参数放入历史文档中
            historyDoc.append("param", new VtuzxMap("STK_InStock", inStockParam));
            // 调用金蝶接口保存入库单
            List<VtuzxMap> stkInStockList = kingdeeService.save(client, "STK_InStock", inStockParam);
            // 获取保存后的入库单信息
            VtuzxMap stkInStockMap = stkInStockList.get(0);
            // 获取入库单号
            number = VtuzxUtil.getString(stkInStockMap, "Number");
            // 调用金蝶接口提交入库单
            kingdeeService.submit(client, "STK_InStock", "0", number);
            // 调用金蝶接口审核入库单
            kingdeeService.audit(client, "STK_InStock", "0", number, "STK_InvCheckResult");
            // 将入库单号放入历史文档中
            historyDoc.append("kingdeeNumber", number);
            // 标记入库单是否为采购订单
            historyDoc.append("purInOrder", true);
        }
    }

    @Override
    public VtuzxMap getSyncOrderHistory(ObjectId userId, String name, Map<String, Object> param) {
        Criteria cond = new Criteria();
        String billNo = VtuzxUtil.getString(param, "billNo");
        String event = VtuzxUtil.getString(param, "event");
        String userName = VtuzxUtil.getString(param, "userName");
        Boolean success = VtuzxUtil.getBoolean(param, "success");//同步状态
        List<String> updateTime = VtuzxUtil.getObject(param, "updateTime");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");

        if (!VtuzxUtil.isEmpty(userName)) {
            cond.and("userName").regex(userName);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(event)) {
            cond.and("event").regex(event);
        }
        if (!VtuzxUtil.isEmpty(updateTime)) {
            cond.and("updateTime").gte(VtuzxUtil.parseDate(updateTime.get(0))).lte(VtuzxUtil.parseDate(updateTime.get(1) + " 23:59:59"));
        }

        VtuzxPage page = syncOrderDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("event", VtuzxUtil.getString(doc, "event"))
                .append("userName", VtuzxUtil.getString(doc, "userName"))
                .append("updateUserName", VtuzxUtil.getString(doc, "updateUserName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime")))
                .append("updateTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "updateTime")))
                .append("data", VtuzxUtil.getObject(doc, "data"))
                .append("detailData", VtuzxUtil.getObject(doc, "detailData"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("createUserId", VtuzxUtil.getString(doc, "createUserId"))
                .append("success", VtuzxUtil.getBoolean(doc, "success"))
                .append("param", VtuzxUtil.getObject(doc, "param"))
                .append("message", VtuzxUtil.getString(doc, "message"))
                .append("kingdeeNumber", VtuzxUtil.getString(doc, "kingdeeNumber")));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public void syncOtherInOrder(ObjectId userId, String name, String billNo, String source) throws Exception {

        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        boolean success = VtuzxUtil.getBoolean(historyDoc, "success");
//        if (success) {
//            return;
//        }
        Document otherIn = otherInDao.findOne(Criteria.where("billNo").is(billNo));

        historyDoc.append("billNo", billNo);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("source", source);
        historyDoc.append("data", otherIn);
        historyDoc.append("event", "otherInStock");
        try {
            syncOtherInOrderInner(historyDoc);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("otherInOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }

    }

    private void syncOtherInOrderInner(Document historyDoc) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");
        Document otherIn = VtuzxUtil.getObject(historyDoc, "data");
        String createUserName = VtuzxUtil.getString(otherIn, "createUserName");
        String remark = VtuzxUtil.getString(otherIn, "remark");
        String auditUserName = VtuzxUtil.getString(otherIn, "auditUserName");
        String createTime = VtuzxUtil.formatYmdF(VtuzxUtil.getObject(otherIn, "createTime"));
        String auditTime = VtuzxUtil.formatYmdF(VtuzxUtil.getObject(otherIn, "auditTime"));
        List<VtuzxMap> materialList = new ArrayList<>();
        List<String> materialNoList = new ArrayList<>();
        Iterator<Document> otherInItr = otherInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (otherInItr.hasNext()) {
            Document otherInDoc = otherInItr.next();
            VtuzxMap otherInMap = new VtuzxMap(otherInDoc);
            String materialNumber = VtuzxUtil.getString(otherInMap, "materialNo");
            materialNoList.add(materialNumber);
            materialList.add(otherInMap);
        }

        String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
        List<VtuzxMap> materialQuery = kingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
                        "FIsBatchManage",
                        "FNumber"
                ),
                String.format("FNumber in (%s)", materialNoCond), null, 0, 1);
        if (VtuzxUtil.isEmpty(materialQuery)) return;

        VtuzxMap materialMap = new VtuzxMap();
        for (VtuzxMap material : materialQuery) {
            String number = VtuzxUtil.getString(material, "FNumber");
            boolean isBatchManage = VtuzxUtil.getBoolean(material, "FIsBatchManage");
            materialMap.append(number, isBatchManage);
        }

        VtuzxMap inStockParam = new VtuzxMap();
        VtuzxMap inStockModel = new VtuzxMap();
        List<Map<String, Object>> fInStockEntry = new ArrayList<>();

        for (Map<String, Object> material : materialList) {
            String materialNo = VtuzxUtil.getString(material, "materialNo");
            boolean isBatchManage = VtuzxUtil.getBoolean(materialMap, materialNo);
            String batchNo = VtuzxUtil.getString(material, "batchNo");
            String stockNo = VtuzxUtil.getString(material, "stockNo");
            String unit = VtuzxUtil.getString(material, "unit");
            double count = Math.abs(VtuzxUtil.getDouble(material, "count"));

            Map<String, Object> detailMap = new LinkedHashMap<>();
            detailMap.put("FUnitID", new VtuzxMap("FNumber", unit));
            detailMap.put("FMATERIALID", new VtuzxMap("FNumber", materialNo));
            detailMap.put("FSTOCKID", new VtuzxMap("FNumber", stockNo));
            detailMap.put("FOWNERID", new VtuzxMap("FNumber", "100"));
            detailMap.put("FBASEQTY", new VtuzxMap("FNumber", unit));
            detailMap.put("FLOT", new VtuzxMap("FNumber", batchNo));
            detailMap.put("FQty", count);
            fInStockEntry.add(detailMap);
        }
        inStockModel.append("FEntity", fInStockEntry)
                .append("FSupplierId", new VtuzxMap("FNumber", "01.01"))
                .append("FNOTE", remark)
                .append("F_qtrkd_ZTDJH", billNo)
                .append("F_qtrkd_CZRY", createUserName)
                .append("F_qtrkd_FHR", auditUserName)
                .append("F_qtrkd_SJLY", source)
                .append("F_qtrkd_ZTYWRQ", createTime)
                .append("F_qtrkd_ZTRKSJ", auditTime)
                .append("F_qtrkd_ZTRKR", auditUserName);

        inStockParam.append("model", inStockModel);
        historyDoc.append("param", new VtuzxMap("STK_MISCELLANEOUS", inStockParam));
        List<VtuzxMap> stkInStockList = kingdeeService.save(client, "STK_MISCELLANEOUS", inStockParam);
        VtuzxMap stkInStockMap = stkInStockList.get(0);
        String number = VtuzxUtil.getString(stkInStockMap, "Number");
        kingdeeService.submit(client, "STK_MISCELLANEOUS", "0", number);
        kingdeeService.audit(client, "STK_MISCELLANEOUS", "0", number, "STK_InvCheckResult");

        historyDoc.append("kingdeeNumber", number);
        historyDoc.append("otherInStock", true);

    }

    @Override
    public void syncOtherOutOrder(ObjectId userId, String name, String billNo, String source) throws Exception {

        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        boolean success = VtuzxUtil.getBoolean(historyDoc, "success");
//        if (success) {
//            return;
//        }
        Document otherOut = otherOutDao.findOne(Criteria.where("billNo").is(billNo));

        historyDoc.append("billNo", billNo);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("source", source);
        historyDoc.append("data", otherOut);
        historyDoc.append("event", "otherOutStock");
        try {
            syncOtherOutOrderInner(historyDoc);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("otherOutStock", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    @Override
    public void syncOtherOutOrderInner(Document historyDoc) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
//        VtuzxMap optionParam = new VtuzxMap();
//        List<String> optionKeys = new ArrayList<>();
//        optionKeys.add("otherOut");
//        optionParam.append("keys", optionKeys);
//
//        VtuzxMap optionsMap = getOptions(optionParam);
//        List<VtuzxMap> otherOutOptions = VtuzxUtil.getObject(optionsMap, "otherOut");
//        VtuzxMap otherOutOptionMap = list2Map(otherOutOptions, "key");
//
//        VtuzxMap baseCurrIdMap = VtuzxUtil.getObject(otherOutOptionMap, "baseCurrId");
//        String baseCurrIdKey = VtuzxUtil.getString(baseCurrIdMap, "name");
//        VtuzxMap billTypeMap = VtuzxUtil.getObject(otherOutOptionMap, "billType");
//        String billTypeKey = VtuzxUtil.getString(billTypeMap, "name");
//        VtuzxMap keeperIdMap = VtuzxUtil.getObject(otherOutOptionMap, "keeperId");
//        String keeperIdKey = VtuzxUtil.getString(keeperIdMap, "name");
//        VtuzxMap keeperTypeIdMap = VtuzxUtil.getObject(otherOutOptionMap, "keeperTypeId");
//        String keeperTypeIdKey = VtuzxUtil.getString(keeperTypeIdMap, "name");
//        VtuzxMap ownerIdMap = VtuzxUtil.getObject(otherOutOptionMap, "ownerId");
//        String ownerIdKey = VtuzxUtil.getString(ownerIdMap, "name");
//        VtuzxMap ownerIdHeadMap = VtuzxUtil.getObject(otherOutOptionMap, "ownerIdHead");
//        String ownerIdHeadKey = VtuzxUtil.getString(ownerIdHeadMap, "name");
//        VtuzxMap ownerTypeIdMap = VtuzxUtil.getObject(otherOutOptionMap, "ownerTypeId");
//        String ownerTypeIdKey = VtuzxUtil.getString(ownerTypeIdMap, "name");
//        VtuzxMap ownerTypeIdHeadMap = VtuzxUtil.getObject(otherOutOptionMap, "ownerTypeIdHead");
//        String ownerTypeIdHeadKey = VtuzxUtil.getString(ownerTypeIdHeadMap, "name");
//        VtuzxMap pickOrgIdMap = VtuzxUtil.getObject(otherOutOptionMap, "pickOrgId");
//        String pickOrgIdKey = VtuzxUtil.getString(pickOrgIdMap, "name");
//        VtuzxMap stockDirectMap = VtuzxUtil.getObject(otherOutOptionMap, "stockDirect");
//        String stockDirectKey = VtuzxUtil.getString(stockDirectMap, "name");
//        VtuzxMap stockOrgIdMap = VtuzxUtil.getObject(otherOutOptionMap, "stockOrgId");
//        String stockOrgIdKey = VtuzxUtil.getString(stockOrgIdMap, "name");
//        VtuzxMap stockStatusIdMap = VtuzxUtil.getObject(otherOutOptionMap, "stockStatusId");
//        String stockStatusIdKey = VtuzxUtil.getString(stockStatusIdMap, "name");

        Document otherOut = VtuzxUtil.getObject(historyDoc, "data");
        String remark = VtuzxUtil.getString(otherOut, "remark");
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");
        String createUserName = VtuzxUtil.getString(otherOut, "createUserName");
        String auditUserName = VtuzxUtil.getString(otherOut, "auditUserName");
        Date createTime = VtuzxUtil.getObject(otherOut, "auditTime");
        List<VtuzxMap> materialList = new ArrayList<>();
        List<String> materialNoList = new ArrayList<>();
        Iterator<Document> otherOutItr = otherOutDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (otherOutItr.hasNext()) {
            Document otherOutDoc = otherOutItr.next();
            VtuzxMap otherOutMap = new VtuzxMap(otherOutDoc);
            String materialNumber = VtuzxUtil.getString(otherOutMap, "materialNo");
            materialNoList.add(materialNumber);
            materialList.add(otherOutMap);
        }


        String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
        List<VtuzxMap> materialQuery = kingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
                        "FIsBatchManage",
                        "FNumber"
                ),
                String.format("FNumber in (%s)", materialNoCond), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialQuery)) return;

        VtuzxMap materialMap = new VtuzxMap();
        for (VtuzxMap material : materialQuery) {
            String number = VtuzxUtil.getString(material, "FNumber");
            boolean isBatchManage = VtuzxUtil.getBoolean(material, "FIsBatchManage");
            materialMap.append(number, isBatchManage);
        }
        String number = "";
        VtuzxMap outStockParam = new VtuzxMap();
        VtuzxMap outStockModel = new VtuzxMap();
        List<Map<String, Object>> fOutStockEntry = new ArrayList<>();

        VtuzxMap materialCenterMap = new VtuzxMap();
        Iterator<Document> materialItr = materialDao.findList(Criteria.where("fNumber").in(materialNoList), null, 0, 0);
        while (materialItr.hasNext()) {
            Document materialDoc = materialItr.next();
            String materialNo = VtuzxUtil.getString(materialDoc, "fNumber");
            String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
            materialCenterMap.append(materialNo, unit);
        }


        for (Map<String, Object> material : materialList) {
            String materialNo = VtuzxUtil.getString(material, "materialNo");
            boolean isBatchManage = VtuzxUtil.getBoolean(materialMap, materialNo);
            String stockNo = VtuzxUtil.getString(material, "stockNo");
            String unit = VtuzxUtil.getString(materialCenterMap, materialNo);
            if (VtuzxUtil.isEmpty(unit)) {
                throw new VtuzxException(String.format("物料[%s]不存在", materialNo));
            }
            String batchNo = VtuzxUtil.getString(material, "batchNo");
            double count = Math.abs(VtuzxUtil.getDouble(material, "count"));

            Map<String, Object> detailMap = new LinkedHashMap<>();
            detailMap.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
            detailMap.put("FUnitID", new VtuzxMap("FNumber", unit));
            detailMap.put("FBaseUnitId", new VtuzxMap("FNumber", unit));
            detailMap.put("FStockId", new VtuzxMap("FNumber", stockNo));
            if (isBatchManage) {
                detailMap.put("FLot", new VtuzxMap("FNumber", batchNo));
            }
            detailMap.put("FOwnerTypeId", "BD_OwnerOrg");
            detailMap.put("FOwnerId", new VtuzxMap("FNumber", "100"));
            detailMap.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
            detailMap.put("FKeeperId", new VtuzxMap("FNumber", "100"));
            detailMap.put("FKeeperTypeId", "BD_KeeperOrg");
            detailMap.put("FQty", count);
            fOutStockEntry.add(detailMap);
        }
        outStockModel.append("FEntity", fOutStockEntry)
                .append("FBillTypeID", new VtuzxMap("FNumber", "QTCKD01_SYS"))
                .append("FStockOrgId", new VtuzxMap("FNumber", "100"))
                .append("FPickOrgId", new VtuzxMap("FNumber", "100"))
                .append("FStockDirect", "GENERAL")
                .append("FDate", VtuzxUtil.formatYmdF(createTime))
                .append("FOwnerTypeIdHead", "BD_OwnerOrg")
                .append("FOwnerIdHead", new VtuzxMap("FNumber", "100"))
                .append("FBaseCurrId", new VtuzxMap("FNumber", "PRE001"))
                .append("FDeptId", new VtuzxMap("FNumber", "01.01"))
                .append("FNOTE", remark)
                .append("F_qtckd_ZTDJH", billNo)
                .append("F_qtckd_CZRY", createUserName)
                .append("F_qtckd_FHR", auditUserName)
                .append("F_qtckd_SJLY", source)
                .append("F_qtckd_ZTYWRQ", VtuzxUtil.formatYmdF(createTime));

        outStockParam.append("model", outStockModel);
        historyDoc.append("param", new VtuzxMap("STK_MisDelivery", outStockParam));
        List<VtuzxMap> stkOutStockList = kingdeeService.save(client, "STK_MisDelivery", outStockParam);
        VtuzxMap stkOutStockMap = stkOutStockList.get(0);
        number = VtuzxUtil.getString(stkOutStockMap, "Number");
        kingdeeService.submit(client, "STK_MisDelivery", "0", number);
        kingdeeService.audit(client, "STK_MisDelivery", "0", number, "STK_InvCheckResult");

        historyDoc.append("kingdeeNumber", number);
        historyDoc.append("otherOutStock", true);
    }

    @Override
    public void retry(VtuzxToken token, String historyId) throws Exception {
        Document history = syncOrderDao.findById(historyId);
        String event = VtuzxUtil.getString(history, "event");
        boolean success = VtuzxUtil.getBoolean(history, "success");
        if (success) {
            throw new VtuzxException("履历处理成功，不需要重试");
        }
        if ("otherOutStock".equals(event)) {
            _logger.info(String.format("开始重推[%s]类型的履历", event));
            syncOtherOutOrderInner(history);
        }
    }

    @Override
    public void syncPrdOrder(ObjectId userId, String name, String billNo, String source, String taskTime) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }

        Document prdOrderDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));

        historyDoc.append("billNo", billNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", prdOrderDoc);
        historyDoc.append("event", "prdOrder");
        historyDoc.append("taskTime", taskTime);
        try {
            syncPrdOrderInner(historyDoc);

            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    @Override
    public void syncPrdOrderBn(ObjectId userId, String name, String billNo, String source, String taskTime) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        Document prdOrderDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));
        historyDoc.append("billNo", billNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", prdOrderDoc);
        historyDoc.append("type", "product");
        historyDoc.append("event", "prdOrder");
        historyDoc.append("taskTime", taskTime);
        try {
            syncPrdOrderInnerBn(historyDoc);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    //分选订单
    private String syncPrdOrderInner(Document historyDoc) throws Exception {
        VtuzxMap optionParam = new VtuzxMap();
        List<String> optionKeys = new ArrayList<>();
        optionKeys.add("prdOrder");
        optionParam.append("keys", optionKeys);
        VtuzxMap optionsMap = getOptions(optionParam);
        List<VtuzxMap> prdOrderOptions = VtuzxUtil.getObject(optionsMap, "prdOrder");
        VtuzxMap prdOrderOptionMap = list2Map(prdOrderOptions, "key");

        VtuzxMap inStockOwnerIdMap = VtuzxUtil.getObject(prdOrderOptionMap, "inStockOwnerId");
        String inStockOwnerIdKey = VtuzxUtil.getString(inStockOwnerIdMap, "name");
        VtuzxMap billTypeMap = VtuzxUtil.getObject(prdOrderOptionMap, "billType");
        String billTypeKey = VtuzxUtil.getString(billTypeMap, "name");
        VtuzxMap inStockOwnerTypeIdMap = VtuzxUtil.getObject(prdOrderOptionMap, "inStockOwnerTypeId");
        String inStockOwnerTypeIdKey = VtuzxUtil.getString(inStockOwnerTypeIdMap, "name");
        VtuzxMap ownerTypeIdMap = VtuzxUtil.getObject(prdOrderOptionMap, "ownerTypeId");
        String ownerTypeIdKey = VtuzxUtil.getString(ownerTypeIdMap, "name");
        VtuzxMap prdOrgIdMap = VtuzxUtil.getObject(prdOrderOptionMap, "prdOrgId");
        String prdOrgIdKey = VtuzxUtil.getString(prdOrgIdMap, "name");
        VtuzxMap requestOrgIdMap = VtuzxUtil.getObject(prdOrderOptionMap, "requestOrgId");
        String requestOrgIdKey = VtuzxUtil.getString(requestOrgIdMap, "name");
        VtuzxMap stockInOrgIdMap = VtuzxUtil.getObject(prdOrderOptionMap, "stockInOrgId");
        String stockInOrgIdKey = VtuzxUtil.getString(stockInOrgIdMap, "name");
        VtuzxMap costRateMap = VtuzxUtil.getObject(prdOrderOptionMap, "costRate");
        double costRateKey = VtuzxUtil.getDouble(costRateMap, "name");
        VtuzxMap yieldRateMap = VtuzxUtil.getObject(prdOrderOptionMap, "yieldRate");
        double yieldRateKey = VtuzxUtil.getDouble(yieldRateMap, "name");
        VtuzxMap createTypeMap = VtuzxUtil.getObject(prdOrderOptionMap, "createType");
        String createTypeKey = VtuzxUtil.getString(createTypeMap, "name");
        VtuzxMap groupMap = VtuzxUtil.getObject(prdOrderOptionMap, "group");
        String groupKey = VtuzxUtil.getString(groupMap, "name");

        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        Document prdOrder = VtuzxUtil.getObject(historyDoc, "data");
        String taskTime = VtuzxUtil.getString(historyDoc, "taskTime");//订单日期
        String produceHouseNo = VtuzxUtil.getString(prdOrder, "produceHouseNo");

        //查询金蝶部门
        List<VtuzxMap> departmentQuery = kingdeeService.query(client, "BD_Department", new VtuzxArrayList<>(
                        "FNumber1",
                        "FNumber"
                ),
                String.format("FNumber1 = '%s'", produceHouseNo), null, 0, 1);
        if (VtuzxUtil.isEmpty(departmentQuery)) {
            throw new VtuzxException(String.format("部门[%s]在金蝶中不存在", produceHouseNo));
        }
        String department = VtuzxUtil.getString(departmentQuery.get(0), "FNumber");

        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String type = VtuzxUtil.getString(historyDoc, "type");
        String source = VtuzxUtil.getString(historyDoc, "source");
        String createUserName = VtuzxUtil.getString(prdOrder, "createUserName");
        String auditUserName = VtuzxUtil.getString(prdOrder, "auditUserName");
        Date createTime = VtuzxUtil.getObject(prdOrder, "createTime");
        Date auditTime = VtuzxUtil.getObject(prdOrder, "auditTime");
        List<VtuzxMap> materialList = new ArrayList<>();

        if ("sorting".equals(type)) {
            materialList.add(new VtuzxMap(prdOrder));
        } else {
            Iterator<Document> prdTaskItr = prdTaskDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
            while (prdTaskItr.hasNext()) {
                Document prdTaskDoc = prdTaskItr.next();
                VtuzxMap prdTaskMap = new VtuzxMap(prdTaskDoc);
                materialList.add(prdTaskMap);
            }
        }
        String number = "";
        VtuzxMap prdOrderParam = new VtuzxMap();
        Map<String, Object> prdOrderModel = new LinkedHashMap<>();
        List<Map<String, Object>> fOutStockEntry = new ArrayList<>();

        for (Map<String, Object> material : materialList) {
            String materialNo = VtuzxUtil.getString(material, "materialNo");
            String batchNo = VtuzxUtil.getString(material, "batchNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            if (VtuzxUtil.isEmpty(materialDoc)) {
                throw new VtuzxException(String.format("编码为[%s]的物料不存在", materialNo));
            }
            String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
            double count = Math.abs(VtuzxUtil.getDouble(material, "count"));
            //保留两位小数
            count = BigDecimal.valueOf(Math.abs(count)).setScale(2, RoundingMode.HALF_UP).doubleValue();

            Map<String, Object> detailMap = new LinkedHashMap<>();
            detailMap.put("FProductType", "1");
            detailMap.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
            detailMap.put("FWorkShopID", new VtuzxMap("FNumber", department));
            detailMap.put("FUnitId", new VtuzxMap("FNumber", unit));
            detailMap.put("FQty", count);
            detailMap.put("FYieldQty", count);
//            detailMap.put("FPlanStartDate", VtuzxUtil.formatYmdHmsF(createTime));//计划开工日期
//            detailMap.put("FPlanFinishDate", VtuzxUtil.formatYmdHmsF(createTime));//计划完工日期
            detailMap.put("FRequestOrgId", new VtuzxMap("FNumber", requestOrgIdKey));
            detailMap.put("FISBACKFLUSH", true);
            detailMap.put("FLot", new VtuzxMap("FNumber", batchNo));//批次
            detailMap.put("FStockInOrgId", new VtuzxMap("FNumber", stockInOrgIdKey));
            detailMap.put("FBaseYieldQty", count);
            detailMap.put("FInStockOwnerTypeId", inStockOwnerTypeIdKey);
            detailMap.put("FBaseStockInLimitH", count);
            detailMap.put("FInStockOwnerId", new VtuzxMap("FNumber", inStockOwnerIdKey));
            detailMap.put("FCheckProduct", false);
            detailMap.put("FBaseStockInLimitL", count);
            detailMap.put("FBaseUnitQty", count);
            detailMap.put("FBaseUnitId", new VtuzxMap("FNumber", unit));
            detailMap.put("FStockInLimitH", count);
            detailMap.put("FStockInLimitL", count);
            detailMap.put("FCostRate", costRateKey);
            detailMap.put("FCreateType", createTypeKey);
            detailMap.put("FYieldRate", yieldRateKey);
            detailMap.put("FGroup", groupKey);
            detailMap.put("FNoStockInQty", count);
            detailMap.put("FBaseNoStockInQty", count);
            detailMap.put("FRowId", "ba36ddd9-bb80-80b7-11ed-4f73ea562f1d");
            detailMap.put("FScheduleStatus", "1");
            detailMap.put("FPickMtrlStatus", "1");
            detailMap.put("FMOChangeFlag", false);
            detailMap.put("FIsFirstInspect", false);
            detailMap.put("FFirstInspectStatus", "A");

            fOutStockEntry.add(detailMap);
        }
        prdOrderModel.put("FID", 0);
        prdOrderModel.put("FBillType", new VtuzxMap("FNumber", billTypeKey));
        //当日期为空或者日期为“Invalid Date”时，说明没有手动选择日期
        if ("Invalid Date".equals(taskTime) || VtuzxUtil.isEmpty(taskTime)) {
            prdOrderModel.put("FDate", VtuzxUtil.formatYmdHmsF(createTime));
        } else {
            prdOrderModel.put("FDate", taskTime);
        }

        prdOrderModel.put("FPrdOrgId", new VtuzxMap("FNumber", prdOrgIdKey));
        prdOrderModel.put("FWorkShopID0", new VtuzxMap("FNumber", department));
        prdOrderModel.put("FOwnerTypeId", ownerTypeIdKey);
        prdOrderModel.put("FIsRework", false);
        prdOrderModel.put("FBusinessType", "1");
        prdOrderModel.put("FTrustteed", false);
        prdOrderModel.put("FIsEntrust", false);
        prdOrderModel.put("FPPBOMType", "1");
        prdOrderModel.put("FIssueMtrl", false);
        prdOrderModel.put("F_scdd_ZTSQR", createUserName);
        prdOrderModel.put("F_scdd_ZTSQSJ", VtuzxUtil.formatYmdHmsF(createTime));
        prdOrderModel.put("F_scdd_ZTSHR", auditUserName);
        prdOrderModel.put("F_scdd_ZTDJH", billNo);
        prdOrderModel.put("F_scdd_SJLY", source);
        prdOrderModel.put("F_scdd_ZTSHSJ", VtuzxUtil.formatYmdHmsF(auditTime));
        prdOrderModel.put("FTreeEntity", fOutStockEntry);

        prdOrderParam.append("Model", prdOrderModel);
        historyDoc.append("param", new VtuzxMap("PRD_MO", prdOrderParam));
        //修改订单的下达时间为订单的创建时间


        List<VtuzxMap> stkOutStockList = kingdeeService.save(client, "PRD_MO", prdOrderParam);
        VtuzxMap stkOutStockMap = stkOutStockList.get(0);
        number = VtuzxUtil.getString(stkOutStockMap, "Number");
        kingdeeService.submit(client, "PRD_MO", "0", number);
        kingdeeService.audit(client, "PRD_MO", "0", number, "STK_InvCheckResult");
        historyDoc.append("kingdeeNumber", number);
        historyDoc.append("prdOrder", true);
        return number;
    }

    //分选订单BN
    private String syncPrdOrderInnerBn(Document historyDoc) throws Exception {
        VtuzxMap optionParam = new VtuzxMap();
        List<String> optionKeys = new ArrayList<>();
        optionKeys.add("prdOrder");
        optionParam.append("keys", optionKeys);
        VtuzxMap optionsMap = getOptions(optionParam);
        List<VtuzxMap> prdOrderOptions = VtuzxUtil.getObject(optionsMap, "prdOrder");
        VtuzxMap prdOrderOptionMap = list2Map(prdOrderOptions, "key");
        VtuzxMap inStockOwnerIdMap = VtuzxUtil.getObject(prdOrderOptionMap, "inStockOwnerId");
        String inStockOwnerIdKey = VtuzxUtil.getString(inStockOwnerIdMap, "name");
        VtuzxMap billTypeMap = VtuzxUtil.getObject(prdOrderOptionMap, "billType");
        String billTypeKey = VtuzxUtil.getString(billTypeMap, "name");
        VtuzxMap inStockOwnerTypeIdMap = VtuzxUtil.getObject(prdOrderOptionMap, "inStockOwnerTypeId");
        String inStockOwnerTypeIdKey = VtuzxUtil.getString(inStockOwnerTypeIdMap, "name");
        VtuzxMap ownerTypeIdMap = VtuzxUtil.getObject(prdOrderOptionMap, "ownerTypeId");
        String ownerTypeIdKey = VtuzxUtil.getString(ownerTypeIdMap, "name");
        VtuzxMap prdOrgIdMap = VtuzxUtil.getObject(prdOrderOptionMap, "prdOrgId");
        String prdOrgIdKey = VtuzxUtil.getString(prdOrgIdMap, "name");
        VtuzxMap requestOrgIdMap = VtuzxUtil.getObject(prdOrderOptionMap, "requestOrgId");
        String requestOrgIdKey = VtuzxUtil.getString(requestOrgIdMap, "name");
        VtuzxMap stockInOrgIdMap = VtuzxUtil.getObject(prdOrderOptionMap, "stockInOrgId");
        String stockInOrgIdKey = VtuzxUtil.getString(stockInOrgIdMap, "name");
        VtuzxMap costRateMap = VtuzxUtil.getObject(prdOrderOptionMap, "costRate");
        double costRateKey = VtuzxUtil.getDouble(costRateMap, "name");
        VtuzxMap yieldRateMap = VtuzxUtil.getObject(prdOrderOptionMap, "yieldRate");
        double yieldRateKey = VtuzxUtil.getDouble(yieldRateMap, "name");
        VtuzxMap createTypeMap = VtuzxUtil.getObject(prdOrderOptionMap, "createType");
        String createTypeKey = VtuzxUtil.getString(createTypeMap, "name");
        VtuzxMap groupMap = VtuzxUtil.getObject(prdOrderOptionMap, "group");
        String groupKey = VtuzxUtil.getString(groupMap, "name");
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdeeYX();
        Document prdOrder = VtuzxUtil.getObject(historyDoc, "data");
        String taskTime = VtuzxUtil.getString(historyDoc, "taskTime");//订单日期
        String produceHouseNo = VtuzxUtil.getString(prdOrder, "produceHouseNo");
        /*//查询金蝶部门
        List<VtuzxMap> departmentQuery = kingdeeService.query(client, "BD_Department", new VtuzxArrayList<>(
                        "FNumber1",
                        "FNumber"
                ),
                String.format("FNumber1 = '%s'", produceHouseNo), null, 0, 1);
        if (VtuzxUtil.isEmpty(departmentQuery)) {
            throw new VtuzxException(String.format("部门[%s]在金蝶中不存在", produceHouseNo));
        }
        String department = VtuzxUtil.getString(departmentQuery.get(0), "FNumber");*/
        String department = "BM000004";
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String type = VtuzxUtil.getString(historyDoc, "type");
        String source = VtuzxUtil.getString(historyDoc, "source");
        String createUserName = VtuzxUtil.getString(prdOrder, "createUserName");
        String auditUserName = VtuzxUtil.getString(prdOrder, "auditUserName");
        Date createTime = VtuzxUtil.getObject(prdOrder, "createTime");
        Date auditTime = VtuzxUtil.getObject(prdOrder, "auditTime");
        List<VtuzxMap> materialList = new ArrayList<>();
        if ("sorting".equals(type)) {
            materialList.add(new VtuzxMap(prdOrder));
        } else {
            Iterator<Document> prdTaskItr = prdTaskDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
            while (prdTaskItr.hasNext()) {
                Document prdTaskDoc = prdTaskItr.next();
                VtuzxMap prdTaskMap = new VtuzxMap(prdTaskDoc);
                materialList.add(prdTaskMap);
            }
        }
        String number = "";
        VtuzxMap prdOrderParam = new VtuzxMap();
        Map<String, Object> prdOrderModel = new LinkedHashMap<>();
        List<Map<String, Object>> fOutStockEntry = new ArrayList<>();
        for (Map<String, Object> material : materialList) {
            String materialNo = VtuzxUtil.getString(material, "materialNo");
            String batchNo = VtuzxUtil.getString(material, "batchNo");
            Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
            if (VtuzxUtil.isEmpty(materialDoc)) {
                throw new VtuzxException(String.format("编码为[%s]的物料不存在", materialNo));
            }
            String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
            double count = Math.abs(VtuzxUtil.getDouble(material, "count"));
            //保留两位小数
            count = BigDecimal.valueOf(Math.abs(count)).setScale(2, RoundingMode.HALF_UP).doubleValue();
            Map<String, Object> detailMap = new LinkedHashMap<>();
            detailMap.put("FProductType", "1");
            detailMap.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
            detailMap.put("FWorkShopID", new VtuzxMap("FNumber", "BM000004"));
            detailMap.put("FUnitId", new VtuzxMap("FNumber", unit));
            detailMap.put("FQty", count);
            detailMap.put("FYieldQty", count);
//          detailMap.put("FPlanStartDate", VtuzxUtil.formatYmdHmsF(createTime));//计划开工日期
//          detailMap.put("FPlanFinishDate", VtuzxUtil.formatYmdHmsF(createTime));//计划完工日期
            detailMap.put("FRequestOrgId", new VtuzxMap("FNumber", "200"));
            detailMap.put("FISBACKFLUSH", true);
            detailMap.put("FLot", new VtuzxMap("FNumber", batchNo));//批次
            detailMap.put("FStockInOrgId", new VtuzxMap("FNumber", "200"));
            detailMap.put("FBaseYieldQty", count);
            detailMap.put("FInStockOwnerTypeId", inStockOwnerTypeIdKey);
            detailMap.put("FBaseStockInLimitH", count);
            /*detailMap.put("FInStockOwnerId", new VtuzxMap("FNumber", inStockOwnerIdKey));*/
            detailMap.put("FInStockOwnerId", new VtuzxMap("FNumber", "200"));
            detailMap.put("FCheckProduct", false);
            detailMap.put("FBaseStockInLimitL", count);
            detailMap.put("FBaseUnitQty", count);
            detailMap.put("FBaseUnitId", new VtuzxMap("FNumber", unit));
            detailMap.put("FStockInLimitH", count);
            detailMap.put("FStockInLimitL", count);
            detailMap.put("FCostRate", costRateKey);
            detailMap.put("FCreateType", createTypeKey);
            detailMap.put("FYieldRate", yieldRateKey);
            detailMap.put("FGroup", groupKey);
            detailMap.put("FNoStockInQty", count);
            detailMap.put("FBaseNoStockInQty", count);
            detailMap.put("FRowId", "ba36ddd9-bb80-80b7-11ed-4f73ea562f1d");
            detailMap.put("FScheduleStatus", "1");
            detailMap.put("FPickMtrlStatus", "1");
            detailMap.put("FMOChangeFlag", false);
            detailMap.put("FIsFirstInspect", false);
            detailMap.put("FFirstInspectStatus", "A");
            /*detailMap.put("FSTOCKID", new VtuzxMap("FNumber", "001"));*/
            //20251014生产成品“委外库”
            detailMap.put("FSTOCKID", new VtuzxMap("FNumber", "002"));
            fOutStockEntry.add(detailMap);
        }
        String typeName = type.equals("product") ? "半成品、产成品" : "分选";
        prdOrderModel.put("FID", 0);
        prdOrderModel.put("FBillType", new VtuzxMap("FNumber", billTypeKey));
        //当日期为空或者日期为“Invalid Date”时，说明没有手动选择日期
        if ("Invalid Date".equals(taskTime) || VtuzxUtil.isEmpty(taskTime)) {
            prdOrderModel.put("FDate", VtuzxUtil.formatYmdHmsF(createTime));
        } else {
            prdOrderModel.put("FDate", taskTime);
        }
        /*20251015===日期*/
        /*prdOrderModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));*/
        prdOrderModel.put("FPrdOrgId", new VtuzxMap("FNumber", "200"));
        prdOrderModel.put("FWorkShopID0", new VtuzxMap("FNumber", "BM000004"));
        prdOrderModel.put("FOwnerTypeId", ownerTypeIdKey);
        prdOrderModel.put("FIsRework", false);
        prdOrderModel.put("FBusinessType", "1");
        prdOrderModel.put("FTrustteed", false);
        prdOrderModel.put("FIsEntrust", false);
        prdOrderModel.put("FPPBOMType", "1");
        prdOrderModel.put("FIssueMtrl", false);
        prdOrderModel.put("F_scdd_ZTSQR", createUserName);
        prdOrderModel.put("F_scdd_ZTSQSJ", VtuzxUtil.formatYmdHmsF(createTime));
        prdOrderModel.put("F_scdd_ZTSHR", auditUserName);
        prdOrderModel.put("F_scdd_ZTDJH", billNo);
        prdOrderModel.put("F_scdd_SJLY", source);
        prdOrderModel.put("F_scdd_ZTSHSJ", VtuzxUtil.formatYmdHmsF(auditTime));
        prdOrderModel.put("F_PSUH_DJLX", typeName);
        prdOrderModel.put("FTreeEntity", fOutStockEntry);
        prdOrderParam.append("Model", prdOrderModel);
        historyDoc.append("param", new VtuzxMap("PRD_MO", prdOrderParam));
        //修改订单的下达时间为订单的创建时间
        List<VtuzxMap> stkOutStockList = kingdeeService.save(client, "PRD_MO", prdOrderParam);
        VtuzxMap stkOutStockMap = stkOutStockList.get(0);
        number = VtuzxUtil.getString(stkOutStockMap, "Number");
        kingdeeService.submit(client, "PRD_MO", "0", number);
        kingdeeService.audit(client, "PRD_MO", "0", number, "STK_InvCheckResult");
        historyDoc.append("kingdeeNumber", number);
        historyDoc.append("prdOrder", true);
        return number;
    }

    @Override
    // 根据用户ID、名称、单据号、来源、提货时间同步prdPickOrder
    public void syncPrdPickOrder(ObjectId userId, String name, String billNo, String source, String pickTime) throws Exception {
        // 根据单据号查询历史记录
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        // 如果历史记录为空，则创建新的记录
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            // 如果历史记录不为空，则获取记录的ID
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        // 根据billNo查询物料BOM领料单
        Document prdPickOrderDoc = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
        // 获取物料BOM领料单中的boxCount
        int boxCount = VtuzxUtil.getInt(prdPickOrderDoc, "boxCount");
        // 如果boxCount为0，则说明单据分录为0
        if (boxCount == 0) {
            // 将结果添加到historyDoc中
            historyDoc.append("prdReturn", false).append("message", "单据分录为0").append("success", true);
            // 如果id为空，则插入historyDoc
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                // 否则，删除historyDoc中的_id、createTime、updateTime字段，并添加updateUserId和updateUserName字段
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                // 更新syncOrderDao中的id字段
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }
        // 添加订单号
        historyDoc.append("billNo", billNo);
        // 添加用户ID
        historyDoc.append("userId", userId);
        // 添加用户名
        historyDoc.append("userName", name);
        // 添加来源
        historyDoc.append("source", source);
        // 添加数据
        historyDoc.append("data", prdPickOrderDoc);
        // 添加事件
        historyDoc.append("event", "prdPick");
        try {
            // 调用syncPrdPickOrderInner方法，传入historyDoc和pickTime参数
            syncPrdPickOrderInner(historyDoc, pickTime);
            // 将success字段设置为true
            historyDoc.append("success", true);
            // 如果id为null，则调用syncOrderDao的insertOne方法，将historyDoc插入数据库
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
                // 否则，调用syncOrderDao的updateById方法，将historyDoc更新到数据库中
            } else {
                // 移除historyDoc中的_id、createTime、updateTime、message字段
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                // 添加updateUserId和updateUserName字段
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                // 调用syncOrderDao的updateById方法，将historyDoc更新到数据库中
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            // 将prdPickOrder字段设置为false，添加message字段，将success字段设置为false
            historyDoc.append("prdPickOrder", false).append("message", e.getMessage()).append("success", false);
            // 如果id为null，则调用syncOrderDao的insertOne方法，将historyDoc插入数据库
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
                // 否则，调用syncOrderDao的updateById方法，将historyDoc更新到数据库中
            } else {
                // 移除historyDoc中的_id、createTime、updateTime字段
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                // 调用syncOrderDao的updateById方法，将historyDoc更新到数据库中
                syncOrderDao.updateById(id, historyDoc);
            }
            // 抛出异常
            throw e;
        }
    }

    @Override
    public boolean syncPrdPickOrderBn(ObjectId userId, String name, String billNo, String pickBillNo, String source, String pickTime ,boolean uploadFlag) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(pickBillNo));
        ObjectId id = null;
        int countSum = 0;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", pickBillNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        Document prdPickOrderDoc = materialBomPickDao.findOne(Criteria.where("billNo").is(pickBillNo));
        /*int boxCount = VtuzxUtil.getInt(prdPickOrderDoc, "boxCount");*/
        //查询明细
        Iterator<Document> materialBomPickDetailItr = materialBomPickDetailDao.findList(
                Criteria.where("billNo").is(pickBillNo), null, 0, 0);
        //过滤出批次号以BN开头的有效明细
        List<Document> validDetails = new ArrayList<>();
        while (materialBomPickDetailItr.hasNext()) {
            Document detail = materialBomPickDetailItr.next();
            String batchNo = VtuzxUtil.getString(detail, "batchNo");
            // 关键过滤逻辑：只保留BN开头的批次
            if (batchNo != null && batchNo.toUpperCase().startsWith("BN")) {
                validDetails.add(detail);
            }
        }
        //基于过滤后的明细计算有效分录数
        int validBoxCount = validDetails.size();
        List<Document> validDetailsSupplement = new ArrayList<>();
        if (validBoxCount == 0) {
            uploadFlag = true;
            //领料单数量为0
            int countPick = 0;

            //查补料单
            // 创建一个空的List，用于存储补料单据
            List<Document> supplementList = new ArrayList<>();
            // 根据billNo查询补料单据
            Iterator<Document> supplementItr = materialBomSupplementDao.findList(Criteria.where("taskBillNo").is(billNo), null, 0, 0);
            // 遍历补料单据
            while (supplementItr.hasNext()) {
                // 获取补料单据
                Document supplementDoc = supplementItr.next();
                // 将补料单据添加到List中
                supplementList.add(supplementDoc);
            }
            // 遍历补料单据List
            for (Document supplementDoc : supplementList) {
                // 获取补料单据的单据编号
                String supplementBillNo = VtuzxUtil.getString(supplementDoc, "billNo");
                /*Document prdSupplementOrderDoc = materialBomSupplementDao.findOne(Criteria.where("billNo").is(supplementBillNo));*/
                Iterator<Document> supplementDetailItr = materialBomSupplementDetailDao.findList(Criteria.where("billNo").is(supplementBillNo), null, 0, 0);
                while (supplementDetailItr.hasNext()) {
                    Document detail = supplementDetailItr.next();
                    String batchNo = VtuzxUtil.getString(detail, "batchNo");
                    if (batchNo != null && batchNo.toUpperCase().startsWith("BN")) {
                        validDetailsSupplement.add(detail);
                    }
                }
            }
            //基于过滤后的明细计算有效分录数
            int countSupplement = validDetailsSupplement.size();

            /*//查退料单
            //根据退料单号查询退料单列表
            Iterator<Document> prdInReturnItr = prdInDao.findList(Criteria.where("taskBillNo").is(billNo).and("return").is(true), null, 0, 0);
            //创建退料单号列表
            List<String> returnNoList = new ArrayList<>();//退料单号
            //遍历退料单列表
            while (prdInReturnItr.hasNext()) {
                //获取退料单
                Document prdInReturnDoc = prdInReturnItr.next();
                //获取退料单号
                String returnBillNo = VtuzxUtil.getString(prdInReturnDoc, "billNo");
                //将退料单号添加到列表中
                returnNoList.add(returnBillNo);
            }
            List<Document> validDetailsReturn = new ArrayList<>();
            // 判断returnNoList是否为空
            if (!VtuzxUtil.isEmpty(returnNoList)) {
                // 遍历returnNoList
                for (String returnBillNo : returnNoList) {
                    *//*Document prdReturnOrderDoc = prdInDao.findOne(Criteria.where("billNo").is(returnBillNo));*//*
                    Iterator<Document> returnDetailItr = prdInDetailDao.findList(Criteria.where("billNo").is(returnBillNo), null, 0, 0);
                    while (returnDetailItr.hasNext()) {
                        Document detail = returnDetailItr.next();
                        String batchNo = VtuzxUtil.getString(detail, "batchNo");
                        if (batchNo != null && batchNo.toUpperCase().startsWith("BN")) {
                            validDetailsReturn.add(detail);
                        }
                    }
                }
            }*/
//            int countReturn = validDetailsReturn.size();
            //计算统计数量(领料单数量+补料单数量-退料单数量)
//            int count = countPick + countSupplement - countReturn;
            //补料数量大于0
            if(countSupplement > 0){
                countSum = countSupplement;
            } else {
                // 将结果添加到historyDoc中
                historyDoc.append("prdReturn", false).append("message", "单据分录为0").append("success", true);
                // 如果id为空，则插入historyDoc
                if (id == null) {
                    syncOrderDao.insertOne(historyDoc);
                } else {
                    // 否则，删除historyDoc中的_id、createTime、updateTime字段，并添加updateUserId和updateUserName字段
                    historyDoc.remove("_id");
                    historyDoc.remove("createTime");
                    historyDoc.remove("updateTime");
                    historyDoc.append("updateUserId", userId);
                    historyDoc.append("updateUserName", name);
                    // 更新syncOrderDao中的id字段
                    syncOrderDao.updateById(id, historyDoc);
                }
                return uploadFlag;
            }
        }
        historyDoc.append("billNo", pickBillNo);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("source", source);
        historyDoc.append("data", prdPickOrderDoc);
        historyDoc.append("event", "prdPick");
        if (validBoxCount == 0) {
            historyDoc.append("filteredDetails", validDetailsSupplement);
        } else {
            historyDoc.append("filteredDetails", validDetails);
        }
        try {
            // 调用syncPrdPickOrderInnerBn方法，传入historyDoc和pickTime参数
            syncPrdPickOrderInnerBn(historyDoc, pickTime, countSum);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdPickOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
        return uploadFlag;
    }

    //生产领料单
    private void syncPrdPickOrderInner(Document historyDoc, String pickTime) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        Document prdPickOrder = VtuzxUtil.getObject(historyDoc, "data");
        String source = VtuzxUtil.getString(historyDoc, "source");
        String taskBillNo = VtuzxUtil.getString(prdPickOrder, "taskBillNo");
        String billNo = VtuzxUtil.getString(prdPickOrder, "billNo");
        String createName = VtuzxUtil.getString(prdPickOrder, "createUserName");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdPickOrder, "createTime"));

        List<String> materialNoList = new ArrayList<>();
        List<Document> bomPickList = new ArrayList<>();
        Iterator<Document> materialBomPickDetailItr = materialBomPickDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (materialBomPickDetailItr.hasNext()) {
            Document bomPickDoc = materialBomPickDetailItr.next();
            String materialNo = VtuzxUtil.getString(bomPickDoc, "materialNo");
            materialNoList.add(materialNo);
            bomPickList.add(bomPickDoc);
        }

        String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
        List<VtuzxMap> materialQuery = kingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
                        "FIsBatchManage",
                        "FNumber"
                ),
                String.format("FNumber in (%s)", materialNoCond), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialQuery)) return;

        List<VtuzxMap> inventoryQuery = kingdeeService.query(client, "STK_Inventory", new VtuzxArrayList<>(
                        "FLot.FNumber",
                        "FMaterialId.FNumber",
                        "FStockId.FNumber",
                        "FBaseQty"
                ),
                String.format("FMaterialId.FNumber in (%s) and FBaseQty != 0", materialNoCond), null, 0, 0);

        VtuzxMap materialMap = new VtuzxMap();
        for (VtuzxMap material : materialQuery) {
            String number = VtuzxUtil.getString(material, "FNumber");
            boolean isBatchManage = VtuzxUtil.getBoolean(material, "FIsBatchManage");
            materialMap.append(number, isBatchManage);
        }

        List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                        "FBillNo",
                        "FQty",
                        "FDate"
                ),
                String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 1);

        if (VtuzxUtil.isEmpty(prdOrderQuery)) return;
        String kingdeeBillNo = VtuzxUtil.getString(prdOrderQuery.get(0), "FBillNo");
        //单据创建日期
        String orderDate = VtuzxUtil.getString(prdOrderQuery.get(0), "FDate");
        double fQty = VtuzxUtil.getDouble(prdOrderQuery.get(0), "FQty");

        List<Map<String, Object>> fMaterialBomEntry = new ArrayList<>();

        List<VtuzxMap> materialBomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                        "FID",
                        "FBillNo",
                        "FMOBillNO",
                        "FMaterialID2.FNumber",
                        "FUnitID2.FNumber",
                        "FNeedQty2",
                        "FEntity_FEntryID"
                ),
                String.format("FMOBillNO = '%s'", kingdeeBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialBomQuery)) return;
        String fid = VtuzxUtil.getString(materialBomQuery.get(0), "FID");
        String entryId = VtuzxUtil.getString(materialBomQuery.get(0), "FEntity_FEntryID");

        //留一个原单据的分录
        materialPickInner(materialBomQuery.get(0), fMaterialBomEntry);

        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        //物料清单修改
        for (Document pick : bomPickList) {
            double lastCount = VtuzxUtil.getDouble(pick, "count");
            pick.append("lastCount", lastCount);
            ppBomInner(client, pick, null, fQty, taskBillNo, 0, materialMap, fMaterialBomEntry, false);
        }

        //金蝶即时库存如果查到匹配的物料
        List<Document> depDocList = new ArrayList<>();
        for (Map<String, Object> bomPick : bomPickList) {
            boolean no = false;
            String materialNo = VtuzxUtil.getString(bomPick, "materialNo");
            String batchNo = VtuzxUtil.getString(bomPick, "batchNo");
            String stockNo = VtuzxUtil.getString(bomPick, "stockNo");
            double count = VtuzxUtil.getDouble(bomPick, "count");
            count = BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue();
            for (VtuzxMap inventory : inventoryQuery) {
                String fMaterialId_FNumber = VtuzxUtil.getString(inventory, "FMaterialId.FNumber");
                String fLot_FNumber = VtuzxUtil.getString(inventory, "FLot.FNumber");
                String fStockId_FNumber = VtuzxUtil.getString(inventory, "FStockId.FNumber");
                double qty = VtuzxUtil.getDouble(inventory, "FBaseQty");
                if (materialNo.equals(fMaterialId_FNumber) && batchNo.equals(fLot_FNumber) && stockNo.equals(fStockId_FNumber)) {
                    no = true;
                    if (qty < count) {
                        Document document = new Document("materialNo", materialNo)
                                .append("batchNo", batchNo)
                                .append("stockNo", stockNo)
                                .append("count", BigDecimal.valueOf(count - qty).setScale(2, RoundingMode.HALF_UP).doubleValue());
                        depDocList.add(document);
                    }
                }
            }
            if (!no) {
                depDocList.add(new Document("materialNo", materialNo)
                        .append("batchNo", batchNo)
                        .append("stockNo", stockNo)
                        .append("count", BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue()));
            }
        }
        if (depDocList.size() != 0) {
            otherInInner(client, depDocList, null, billNo, param);
        }


        Map<String, Object> prdPickOrderParam = new LinkedHashMap<>();
        Map<String, Object> prdPickOrderModel = new LinkedHashMap<>();
        prdPickOrderModel.put("FID", fid);
        prdPickOrderModel.put("FEntity", fMaterialBomEntry);
        VtuzxMap otherInData = new VtuzxMap();
        int rowCount = 0;
        for (Map<String, Object> materialBom : fMaterialBomEntry) {
            rowCount++;
            VtuzxMap otherIn = new VtuzxMap();
            VtuzxMap fMaterialIDMap = VtuzxUtil.getObject(materialBom, "FMaterialID2");
            VtuzxMap flotMap = VtuzxUtil.getObject(materialBom, "FLot");
            if (VtuzxUtil.isEmpty(fMaterialIDMap) || VtuzxUtil.isEmpty(flotMap)) {
                otherIn.append("materialNo", "").append("batchNo", "");
            } else {
                String materialNo = VtuzxUtil.getString(fMaterialIDMap, "FNumber");
                String batchNo = VtuzxUtil.getString(flotMap, "FNumber");
                otherIn.append("materialNo", materialNo).append("batchNo", batchNo);
            }
            otherInData.append(String.valueOf(rowCount), otherIn);
        }

        prdPickOrderParam.put("NeedUpDateFields", new ArrayList<>());
        prdPickOrderParam.put("NeedReturnFields", new ArrayList<>());
        prdPickOrderParam.put("IsDeleteEntry", true);
        prdPickOrderParam.put("SubSystemId", "");
        prdPickOrderParam.put("IsVerifyBaseDataField", true);
        prdPickOrderParam.put("IsEntryBatchFill", false);
        prdPickOrderParam.put("ValidateFlag", true);
        prdPickOrderParam.put("NumberSearch", true);
        prdPickOrderParam.put("InterationFlags", "");
        prdPickOrderParam.put("Model", prdPickOrderModel);
        param.append("PRD_PPBOM", prdPickOrderParam);
        List<VtuzxMap> prdPPBomList = kingdeeService.save(client, "PRD_PPBOM", prdPickOrderParam);
        VtuzxMap stkOutStockMap = prdPPBomList.get(0);
        String number = VtuzxUtil.getString(stkOutStockMap, "Number");

        //查新增后的分录id
        List<VtuzxMap> materialBomTwoQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                        "FID",
                        "FBillNo",
                        "FMOBillNO",
                        "FMaterialID2.FNumber",
                        "FUnitID2.FNumber",
                        "FNeedQty2",
                        "FEntity_FEntryID"
                ),
                String.format("FBillNo = '%s'", number), null, 0, 0);

        if (VtuzxUtil.isEmpty(materialBomTwoQuery)) return;

        List<Map<String, Object>> entryIdList = new ArrayList<>();
        for (VtuzxMap materialBomTwo : materialBomTwoQuery) {
            Map<String, Object> map = new LinkedHashMap<>();
            String fEntryID = VtuzxUtil.getString(materialBomTwo, "FEntity_FEntryID");
            if (!fEntryID.equals(entryId)) {
                map.put("FEntryID", fEntryID);
                entryIdList.add(map);
            }
        }

        Map<String, Object> prdPickOrderTwoParam = new LinkedHashMap<>();
        Map<String, Object> prdPickOrderTwoModel = new LinkedHashMap<>();

        prdPickOrderTwoModel.put("FID", fid);
        prdPickOrderTwoModel.put("FEntity", entryIdList);

        prdPickOrderTwoParam.put("NeedUpDateFields", new ArrayList<>());
        prdPickOrderTwoParam.put("NeedReturnFields", new ArrayList<>());
        prdPickOrderTwoParam.put("IsDeleteEntry", true);
        prdPickOrderTwoParam.put("SubSystemId", "");
        prdPickOrderTwoParam.put("IsVerifyBaseDataField", true);
        prdPickOrderTwoParam.put("IsEntryBatchFill", false);
        prdPickOrderTwoParam.put("ValidateFlag", true);
        prdPickOrderTwoParam.put("NumberSearch", true);
        prdPickOrderTwoParam.put("InterationFlags", "");
        prdPickOrderTwoParam.put("Model", prdPickOrderTwoModel);
        param.append("PRD_PPBOM", prdPickOrderTwoParam);
        List<VtuzxMap> prdPPBomsList = kingdeeService.save(client, "PRD_PPBOM", prdPickOrderTwoParam);
        VtuzxMap prdPPBomsMap = prdPPBomsList.get(0);
        String bomNumber = VtuzxUtil.getString(prdPPBomsMap, "Number");
        kingdeeService.submit(client, "PRD_PPBOM", "0", bomNumber);
        kingdeeService.audit(client, "PRD_PPBOM", "0", bomNumber, "STK_InvCheckResult");


        //生产订单执行至开工
        kingdeeService.toRelease(client, "PRD_MO", "ToStart", "0", kingdeeBillNo);
        //修改订单的下达时间为订单的创建时间
        try {
            kingdeeService.orderUpdate(client, "PRD_MO", kingdeeBillNo, orderDate);
        } catch (Exception e) {
            _logger.info(e.getMessage());
        }


        //用料清单下推生产领料
        List<String> bomNumberList = new ArrayList<>();
        bomNumberList.add(bomNumber);
        Map<String, Object> bomToPickMap = new LinkedHashMap<>();
        bomToPickMap.put("Ids", "");
        bomToPickMap.put("Numbers", bomNumberList);
        bomToPickMap.put("EntryIds", "");
        bomToPickMap.put("RuleId", "Org_YBLL");
        bomToPickMap.put("TargetBillTypeId", "");
        bomToPickMap.put("TargetOrgId", 0);
        bomToPickMap.put("IsEnableDefaultRule", false);
        bomToPickMap.put("IsDraftWhenSaveFail", false);
        bomToPickMap.put("CustomParams", new VtuzxMap());
        param.append("PRD_PPBOM", bomToPickMap);
        List<VtuzxMap> pickBillList = kingdeeService.push(client, "PRD_PPBOM", bomToPickMap);
        VtuzxMap pickBillMap = pickBillList.get(0);
        String pickBillNo = VtuzxUtil.getString(pickBillMap, "Number");
        String id = VtuzxUtil.getString(pickBillMap, "Id");

        Map<String, Object> updatePickParam = new LinkedHashMap<>();
        Map<String, Object> updatePickModel = new LinkedHashMap<>();
        updatePickModel.put("FID", id);
        if ("Invalid Date".equals(pickTime) || VtuzxUtil.isEmpty(pickTime)) {
            updatePickModel.put("FDate", createTime);
        } else {
            updatePickModel.put("FDate", pickTime);
        }
        updatePickModel.put("F_sclld_ZTLLR", createName);
        updatePickModel.put("F_sclld_ZTDJH", billNo);
        updatePickModel.put("F_sclld_SJLY", source);
        updatePickModel.put("F_sclld_ZTLLSJ", createTime);
        updatePickParam.put("NeedUpDateFields", new ArrayList<>());
        updatePickParam.put("NeedReturnFields", new ArrayList<>());
        updatePickParam.put("IsDeleteEntry", true);
        updatePickParam.put("SubSystemId", "");
        updatePickParam.put("IsVerifyBaseDataField", true);
        updatePickParam.put("IsEntryBatchFill", false);
        updatePickParam.put("ValidateFlag", true);
        updatePickParam.put("NumberSearch", true);
        updatePickParam.put("InterationFlags", "");
        updatePickParam.put("Model", updatePickModel);

        param.append("PRD_PickMtrl", updatePickParam);
        kingdeeService.save(client, "PRD_PickMtrl", updatePickParam);
        kingdeeService.submit(client, "PRD_PickMtrl", "0", pickBillNo);
        kingdeeService.audit(client, "PRD_PickMtrl", "0", pickBillNo, "STK_InvCheckResult");
        historyDoc.append("kingdeeNumber", pickBillNo);
        historyDoc.append("pickBill", true);

    }

    //生产领料单BN
    private void syncPrdPickOrderInnerBn(Document historyDoc, String pickTime, int countSum) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdeeYX();
        Document prdPickOrder = VtuzxUtil.getObject(historyDoc, "data");
        String source = VtuzxUtil.getString(historyDoc, "source");
        String taskBillNo = VtuzxUtil.getString(prdPickOrder, "taskBillNo");
        String billNo = VtuzxUtil.getString(prdPickOrder, "billNo");
        String createName = VtuzxUtil.getString(prdPickOrder, "createUserName");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdPickOrder, "createTime"));
        List<Document> validDetails = VtuzxUtil.getObject(historyDoc, "filteredDetails");
        List<String> materialNoList = new ArrayList<>();
        //使用过滤结果
        List<Document> bomPickList = new ArrayList<>(validDetails);
        for (Document detail : validDetails) {
            materialNoList.add(VtuzxUtil.getString(detail, "materialNo"));
        }
        /*Iterator<Document> materialBomPickDetailItr = materialBomPickDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (materialBomPickDetailItr.hasNext()) {
            Document bomPickDoc = materialBomPickDetailItr.next();
            String materialNo = VtuzxUtil.getString(bomPickDoc, "materialNo");
            materialNoList.add(materialNo);
            bomPickList.add(bomPickDoc);
        }*/
        String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
        List<VtuzxMap> materialQuery = kingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
                        "FIsBatchManage",
                        "FNumber"
                ),
                String.format("FNumber in (%s)", materialNoCond), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialQuery)) return;

        List<VtuzxMap> inventoryQuery = kingdeeService.query(client, "STK_Inventory", new VtuzxArrayList<>(
                        "FLot.FNumber",
                        "FMaterialId.FNumber",
                        "FStockId.FNumber",
                        "FBaseQty"
                ),
                String.format("FMaterialId.FNumber in (%s) and FBaseQty != 0", materialNoCond), null, 0, 0);

        VtuzxMap materialMap = new VtuzxMap();
        for (VtuzxMap material : materialQuery) {
            String number = VtuzxUtil.getString(material, "FNumber");
            boolean isBatchManage = VtuzxUtil.getBoolean(material, "FIsBatchManage");
            materialMap.append(number, isBatchManage);
        }

        List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                        "FBillNo",
                        "FQty",
                        "FDate"
                ),
                String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 1);

        if (VtuzxUtil.isEmpty(prdOrderQuery)) return;
        String kingdeeBillNo = VtuzxUtil.getString(prdOrderQuery.get(0), "FBillNo");
        //单据创建日期
        String orderDate = VtuzxUtil.getString(prdOrderQuery.get(0), "FDate");
        double fQty = VtuzxUtil.getDouble(prdOrderQuery.get(0), "FQty");

        List<Map<String, Object>> fMaterialBomEntry = new ArrayList<>();

        List<VtuzxMap> materialBomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                        "FID",
                        "FBillNo",
                        "FMOBillNO",
                        "FMaterialID2.FNumber",
                        "FUnitID2.FNumber",
                        "FNeedQty2",
                        "FEntity_FEntryID"
                ),
                String.format("FMOBillNO = '%s'", kingdeeBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialBomQuery)) return;
        String fid = VtuzxUtil.getString(materialBomQuery.get(0), "FID");
        String entryId = VtuzxUtil.getString(materialBomQuery.get(0), "FEntity_FEntryID");

        //留一个原单据的分录
        materialPickInner(materialBomQuery.get(0), fMaterialBomEntry);

        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        //物料清单修改
        for (Document pick : bomPickList) {
            double lastCount = VtuzxUtil.getDouble(pick, "count");
            if(VtuzxUtil.isEmpty(countSum)) {
                pick.append("lastCount", lastCount);
            } else {
                pick.append("lastCount", countSum);
            }
            ppBomInnerBn(client, pick, null, fQty, taskBillNo, 0, materialMap, fMaterialBomEntry, false);
        }

        //金蝶即时库存如果查到匹配的物料
        List<Document> depDocList = new ArrayList<>();
        for (Map<String, Object> bomPick : bomPickList) {
            boolean no = false;
            String materialNo = VtuzxUtil.getString(bomPick, "materialNo");
            String batchNo = VtuzxUtil.getString(bomPick, "batchNo");
            String stockNo = "002";
            double count = VtuzxUtil.getDouble(bomPick, "count");
            count = BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue();
            for (VtuzxMap inventory : inventoryQuery) {
                String fMaterialId_FNumber = VtuzxUtil.getString(inventory, "FMaterialId.FNumber");
                String fLot_FNumber = VtuzxUtil.getString(inventory, "FLot.FNumber");
                String fStockId_FNumber = VtuzxUtil.getString(inventory, "FStockId.FNumber");
                double qty = VtuzxUtil.getDouble(inventory, "FBaseQty");
                if (materialNo.equals(fMaterialId_FNumber) && batchNo.equals(fLot_FNumber) && stockNo.equals(fStockId_FNumber)) {
                    no = true;
                    if (qty < count) {
                        Document document = new Document("materialNo", materialNo)
                                .append("batchNo", batchNo)
                                .append("stockNo", stockNo)
                                .append("count", BigDecimal.valueOf(count - qty).setScale(2, RoundingMode.HALF_UP).doubleValue());
                        depDocList.add(document);
                    }
                }
            }
            if (!no) {
                depDocList.add(new Document("materialNo", materialNo)
                        .append("batchNo", batchNo)
                        .append("stockNo", stockNo)
                        .append("count", BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue()));
            }
        }
        if (depDocList.size() != 0) {
            otherInInnerBn(client, depDocList, null, billNo, param);
        }
        Map<String, Object> prdPickOrderParam = new LinkedHashMap<>();
        Map<String, Object> prdPickOrderModel = new LinkedHashMap<>();
        prdPickOrderModel.put("FID", fid);
        prdPickOrderModel.put("FEntity", fMaterialBomEntry);
        VtuzxMap otherInData = new VtuzxMap();
        int rowCount = 0;
        for (Map<String, Object> materialBom : fMaterialBomEntry) {
            rowCount++;
            VtuzxMap otherIn = new VtuzxMap();
            VtuzxMap fMaterialIDMap = VtuzxUtil.getObject(materialBom, "FMaterialID2");
            VtuzxMap flotMap = VtuzxUtil.getObject(materialBom, "FLot");
            if (VtuzxUtil.isEmpty(fMaterialIDMap) || VtuzxUtil.isEmpty(flotMap)) {
                otherIn.append("materialNo", "").append("batchNo", "");
            } else {
                String materialNo = VtuzxUtil.getString(fMaterialIDMap, "FNumber");
                String batchNo = VtuzxUtil.getString(flotMap, "FNumber");
                otherIn.append("materialNo", materialNo).append("batchNo", batchNo);
            }
            otherInData.append(String.valueOf(rowCount), otherIn);
        }
        prdPickOrderParam.put("NeedUpDateFields", new ArrayList<>());
        prdPickOrderParam.put("NeedReturnFields", new ArrayList<>());
        prdPickOrderParam.put("IsDeleteEntry", true);
        prdPickOrderParam.put("SubSystemId", "");
        prdPickOrderParam.put("IsVerifyBaseDataField", true);
        prdPickOrderParam.put("IsEntryBatchFill", false);
        prdPickOrderParam.put("ValidateFlag", true);
        prdPickOrderParam.put("NumberSearch", true);
        prdPickOrderParam.put("InterationFlags", "");
        prdPickOrderParam.put("Model", prdPickOrderModel);
        param.append("PRD_PPBOM", prdPickOrderParam);
        List<VtuzxMap> prdPPBomList = kingdeeService.save(client, "PRD_PPBOM", prdPickOrderParam);
        VtuzxMap stkOutStockMap = prdPPBomList.get(0);
        String number = VtuzxUtil.getString(stkOutStockMap, "Number");
        //查新增后的分录id
        List<VtuzxMap> materialBomTwoQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                        "FID",
                        "FBillNo",
                        "FMOBillNO",
                        "FMaterialID2.FNumber",
                        "FUnitID2.FNumber",
                        "FNeedQty2",
                        "FEntity_FEntryID"
                ),
                String.format("FBillNo = '%s'", number), null, 0, 0);

        if (VtuzxUtil.isEmpty(materialBomTwoQuery)) return;

        List<Map<String, Object>> entryIdList = new ArrayList<>();
        for (VtuzxMap materialBomTwo : materialBomTwoQuery) {
            Map<String, Object> map = new LinkedHashMap<>();
            String fEntryID = VtuzxUtil.getString(materialBomTwo, "FEntity_FEntryID");
            if (!fEntryID.equals(entryId)) {
                map.put("FEntryID", fEntryID);
                entryIdList.add(map);
            }
        }

        Map<String, Object> prdPickOrderTwoParam = new LinkedHashMap<>();
        Map<String, Object> prdPickOrderTwoModel = new LinkedHashMap<>();

        prdPickOrderTwoModel.put("FID", fid);
        prdPickOrderTwoModel.put("FEntity", entryIdList);

        prdPickOrderTwoParam.put("NeedUpDateFields", new ArrayList<>());
        prdPickOrderTwoParam.put("NeedReturnFields", new ArrayList<>());
        prdPickOrderTwoParam.put("IsDeleteEntry", true);
        prdPickOrderTwoParam.put("SubSystemId", "");
        prdPickOrderTwoParam.put("IsVerifyBaseDataField", true);
        prdPickOrderTwoParam.put("IsEntryBatchFill", false);
        prdPickOrderTwoParam.put("ValidateFlag", true);
        prdPickOrderTwoParam.put("NumberSearch", true);
        prdPickOrderTwoParam.put("InterationFlags", "");
        prdPickOrderTwoParam.put("Model", prdPickOrderTwoModel);
        param.append("PRD_PPBOM", prdPickOrderTwoParam);
        List<VtuzxMap> prdPPBomsList = kingdeeService.save(client, "PRD_PPBOM", prdPickOrderTwoParam);
        VtuzxMap prdPPBomsMap = prdPPBomsList.get(0);
        String bomNumber = VtuzxUtil.getString(prdPPBomsMap, "Number");
        kingdeeService.submit(client, "PRD_PPBOM", "0", bomNumber);
        kingdeeService.audit(client, "PRD_PPBOM", "0", bomNumber, "STK_InvCheckResult");


        //生产订单执行至开工
        kingdeeService.toRelease(client, "PRD_MO", "ToStart", "0", kingdeeBillNo);
        //修改订单的下达时间为订单的创建时间
        try {
            kingdeeService.orderUpdate(client, "PRD_MO", kingdeeBillNo, orderDate);
        } catch (Exception e) {
            _logger.info(e.getMessage());
        }


        //用料清单下推生产领料
        List<String> bomNumberList = new ArrayList<>();
        bomNumberList.add(bomNumber);
        Map<String, Object> bomToPickMap = new LinkedHashMap<>();
        bomToPickMap.put("Ids", "");
        bomToPickMap.put("Numbers", bomNumberList);
        bomToPickMap.put("EntryIds", "");
        bomToPickMap.put("RuleId", VtuzxUtil.getString(prdPushRuleDao.findOne(Criteria
                .where("ruleName").is("PPBOMPushPickMtrl")
                .and("ruleType").is("product")
                .and("tokenType").is("kingdee3")
        ), "ruleId"));
        bomToPickMap.put("TargetBillTypeId", "");
        bomToPickMap.put("TargetOrgId", 0);
        bomToPickMap.put("IsEnableDefaultRule", false);
        bomToPickMap.put("IsDraftWhenSaveFail", false);
        bomToPickMap.put("CustomParams", new VtuzxMap());
        param.append("PRD_PPBOM", bomToPickMap);
        List<VtuzxMap> pickBillList = kingdeeService.push(client, "PRD_PPBOM", bomToPickMap);
        VtuzxMap pickBillMap = pickBillList.get(0);
        String pickBillNo = VtuzxUtil.getString(pickBillMap, "Number");
        String id = VtuzxUtil.getString(pickBillMap, "Id");

        Map<String, Object> updatePickParam = new LinkedHashMap<>();
        Map<String, Object> updatePickModel = new LinkedHashMap<>();
        updatePickModel.put("FID", id);
        if ("Invalid Date".equals(pickTime) || VtuzxUtil.isEmpty(pickTime)) {
            updatePickModel.put("FDate", createTime);
        } else {
            updatePickModel.put("FDate", pickTime);
        }
        /*20251015===日期*/
        /*if ("Invalid Date".equals(pickTime) || VtuzxUtil.isEmpty(pickTime)) {
            updatePickModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));
        } else {
            updatePickModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));
        }*/
        updatePickModel.put("F_sclld_ZTLLR", createName);
        updatePickModel.put("F_sclld_ZTDJH", billNo);
        updatePickModel.put("F_sclld_SJLY", source);
        updatePickModel.put("F_sclld_ZTLLSJ", createTime);
        updatePickParam.put("NeedUpDateFields", new ArrayList<>());
        updatePickParam.put("NeedReturnFields", new ArrayList<>());
        updatePickParam.put("IsDeleteEntry", true);
        updatePickParam.put("SubSystemId", "");
        updatePickParam.put("IsVerifyBaseDataField", true);
        updatePickParam.put("IsEntryBatchFill", false);
        updatePickParam.put("ValidateFlag", true);
        updatePickParam.put("NumberSearch", true);
        updatePickParam.put("InterationFlags", "");
        updatePickParam.put("Model", updatePickModel);

        param.append("PRD_PickMtrl", updatePickParam);
        kingdeeService.save(client, "PRD_PickMtrl", updatePickParam);
        kingdeeService.submit(client, "PRD_PickMtrl", "0", pickBillNo);
        kingdeeService.audit(client, "PRD_PickMtrl", "0", pickBillNo, "STK_InvCheckResult");
        historyDoc.append("kingdeeNumber", pickBillNo);
        historyDoc.append("pickBill", true);

    }

    private void otherInInner(VtuzxKingdeeCloudClient client, List<Document> bomPickList, Map<String, Object> prdPickOrderParam, String billNo, VtuzxMap param) throws Exception {
        Map<String, Object> otherInOrderParam = new LinkedHashMap<>();
        Map<String, Object> otherInOrderModel = new LinkedHashMap<>();
        List<Map<String, Object>> otherInOrderMapList = new ArrayList<>();

        List<String> materialNoList = new ArrayList<>();
        for (Document pick : bomPickList) {
            String materialNo = VtuzxUtil.getString(pick, "materialNo");
            materialNoList.add(materialNo);
        }

        VtuzxMap materialCenterMap = new VtuzxMap();
        Iterator<Document> materialItr = materialDao.findList(Criteria.where("fNumber").in(materialNoList), null, 0, 0);
        while (materialItr.hasNext()) {
            Document materialDoc = materialItr.next();
            String materialNo = VtuzxUtil.getString(materialDoc, "fNumber");
            String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
            materialCenterMap.append(materialNo, unit);
        }

        for (Document pick : bomPickList) {
            Map<String, Object> otherInOrderMap = new LinkedHashMap<>();
            String materialNo = VtuzxUtil.getString(pick, "materialNo");
            String unit = VtuzxUtil.getString(materialCenterMap, materialNo);
            if (VtuzxUtil.isEmpty(unit)) {
                throw new VtuzxException(String.format("物料[%s]不存在", materialNo));
            }
            String batchNo = VtuzxUtil.getString(pick, "batchNo");
            double count = VtuzxUtil.getDouble(pick, "count");
//            count = BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue();
            String stockNo = VtuzxUtil.getString(pick, "stockNo");
            otherInOrderMap.put("FMATERIALID", new VtuzxMap("FNumber", materialNo));
            otherInOrderMap.put("FUnitID", new VtuzxMap("FNumber", unit));
            otherInOrderMap.put("FQty", count);
            otherInOrderMap.put("FSTOCKID", new VtuzxMap("FNumber", stockNo));
            otherInOrderMap.put("FLOT", new VtuzxMap("FNumber", batchNo));
            otherInOrderMap.put("FSTOCKSTATUSID", new VtuzxMap("FNumber", "KCZT01_SYS"));
            otherInOrderMapList.add(otherInOrderMap);
        }
        otherInOrderModel.put("FSUPPLIERID", new VtuzxMap("FNumber", "01.01"));
        otherInOrderModel.put("F_qtrkd_SJLY", "出库负库存补充-" + billNo);
        otherInOrderModel.put("F_qtrkd_ZTDJH", billNo);
        otherInOrderModel.put("FEntity", otherInOrderMapList);

        otherInOrderParam.put("NeedUpDateFields", new ArrayList<>());
        otherInOrderParam.put("NeedReturnFields", new ArrayList<>());
        otherInOrderParam.put("IsDeleteEntry", false);
        otherInOrderParam.put("SubSystemId", "");
        otherInOrderParam.put("IsVerifyBaseDataField", false);
        otherInOrderParam.put("IsEntryBatchFill", true);
        otherInOrderParam.put("ValidateFlag", true);
        otherInOrderParam.put("NumberSearch", true);
        otherInOrderParam.put("InterationFlags", "");
        otherInOrderParam.put("Model", otherInOrderModel);
        param.append("STK_MISCELLANEOUS", otherInOrderParam);
        try {
            List<VtuzxMap> otherInList = kingdeeService.save(client, "STK_MISCELLANEOUS", otherInOrderParam);
            VtuzxMap otherInMap = otherInList.get(0);
            String number = VtuzxUtil.getString(otherInMap, "Number");
            kingdeeService.submit(client, "STK_MISCELLANEOUS", "0", number);
            kingdeeService.audit(client, "STK_MISCELLANEOUS", "0", number, "STK_InvCheckResult");
        } catch (Exception e) {

        }

        if (!VtuzxUtil.isEmpty(prdPickOrderParam)) {
            kingdeeService.save(client, "PRD_PPBOM", prdPickOrderParam);
        } else {
        }

    }

    private void otherInInnerBn(VtuzxKingdeeCloudClient client, List<Document> bomPickList, Map<String, Object> prdPickOrderParam, String billNo, VtuzxMap param) throws Exception {
        Map<String, Object> otherInOrderParam = new LinkedHashMap<>();
        Map<String, Object> otherInOrderModel = new LinkedHashMap<>();
        List<Map<String, Object>> otherInOrderMapList = new ArrayList<>();

        List<String> materialNoList = new ArrayList<>();
        for (Document pick : bomPickList) {
            String materialNo = VtuzxUtil.getString(pick, "materialNo");
            materialNoList.add(materialNo);
        }

        VtuzxMap materialCenterMap = new VtuzxMap();
        Iterator<Document> materialItr = materialDao.findList(Criteria.where("fNumber").in(materialNoList), null, 0, 0);
        while (materialItr.hasNext()) {
            Document materialDoc = materialItr.next();
            String materialNo = VtuzxUtil.getString(materialDoc, "fNumber");
            String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
            materialCenterMap.append(materialNo, unit);
        }

        for (Document pick : bomPickList) {
            Map<String, Object> otherInOrderMap = new LinkedHashMap<>();
            String materialNo = VtuzxUtil.getString(pick, "materialNo");
            String unit = VtuzxUtil.getString(materialCenterMap, materialNo);
            if (VtuzxUtil.isEmpty(unit)) {
                throw new VtuzxException(String.format("物料[%s]不存在", materialNo));
            }
            String batchNo = VtuzxUtil.getString(pick, "batchNo");
            double count = VtuzxUtil.getDouble(pick, "count");
//            count = BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue();
            String stockNo = VtuzxUtil.getString(pick, "stockNo");
            otherInOrderMap.put("FMATERIALID", new VtuzxMap("FNumber", materialNo));
            otherInOrderMap.put("FUnitID", new VtuzxMap("FNumber", unit));
            otherInOrderMap.put("FQty", count);
            /*otherInOrderMap.put("FSTOCKID", new VtuzxMap("FNumber", stockNo));*/
            //修改
            otherInOrderMap.put("FSTOCKID", new VtuzxMap("FNumber", "002"));
            //修改
            otherInOrderMap.put("FLOT", new VtuzxMap("FNumber", batchNo));
            otherInOrderMap.put("FSTOCKSTATUSID", new VtuzxMap("FNumber", "KCZT01_SYS"));
            otherInOrderMapList.add(otherInOrderMap);
        }
        otherInOrderModel.put("FStockOrgId", new VtuzxMap("FNumber", "200"));
        otherInOrderModel.put("FSUPPLIERID", new VtuzxMap("FNumber", "05.0002"));
        otherInOrderModel.put("F_qtrkd_SJLY", "出库负库存补充-" + billNo);
        otherInOrderModel.put("F_qtrkd_ZTDJH", billNo);
        otherInOrderModel.put("FEntity", otherInOrderMapList);
        otherInOrderParam.put("NeedUpDateFields", new ArrayList<>());
        otherInOrderParam.put("NeedReturnFields", new ArrayList<>());
        otherInOrderParam.put("IsDeleteEntry", false);
        otherInOrderParam.put("SubSystemId", "");
        otherInOrderParam.put("IsVerifyBaseDataField", false);
        otherInOrderParam.put("IsEntryBatchFill", true);
        otherInOrderParam.put("ValidateFlag", true);
        otherInOrderParam.put("NumberSearch", true);
        otherInOrderParam.put("InterationFlags", "");
        otherInOrderParam.put("Model", otherInOrderModel);
        param.append("STK_MISCELLANEOUS", otherInOrderParam);
        try {
            List<VtuzxMap> otherInList = kingdeeService.save(client, "STK_MISCELLANEOUS", otherInOrderParam);
            VtuzxMap otherInMap = otherInList.get(0);
            String number = VtuzxUtil.getString(otherInMap, "Number");
            kingdeeService.submit(client, "STK_MISCELLANEOUS", "0", number);
            kingdeeService.audit(client, "STK_MISCELLANEOUS", "0", number, "STK_InvCheckResult");
        } catch (Exception e) {

        }

        if (!VtuzxUtil.isEmpty(prdPickOrderParam)) {
            kingdeeService.save(client, "PRD_PPBOM", prdPickOrderParam);
        } else {
        }

    }

    //修改用料清单
    private void ppBomInner(VtuzxKingdeeCloudClient client, Document materialBomPickDetailDoc, VtuzxMap kingdeePrdOrder, double fQty, String taskBillNo, double materialCount, VtuzxMap materialMap, List<Map<String, Object>> fMaterialBomEntry, boolean last) throws Exception {

        Document taskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String type = VtuzxUtil.getString(taskDoc, "type");
        String materialNo = VtuzxUtil.getString(materialBomPickDetailDoc, "materialNo");
        Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
        boolean isBatchManage = VtuzxUtil.getBoolean(materialMap, materialNo);
        String batchNo = VtuzxUtil.getString(materialBomPickDetailDoc, "batchNo");
        String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
        String stockNo = VtuzxUtil.getString(materialBomPickDetailDoc, "stockNo");
        double count = 0;
        count = VtuzxUtil.getDouble(materialBomPickDetailDoc, "count");

        double bigCount = BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue();
        double denominator = 0d;
        double numerator = 0d;
        if ("sorting".equals(type)) {
            String kingdeeMaterialNo = VtuzxUtil.getString(kingdeePrdOrder, "kingdeeMaterialNo");
            List<VtuzxMap> materialBomQuery = kingdeeService.query(client, "ENG_BOM", new VtuzxArrayList<>(
                            "FMATERIALID.FNUMBER",
                            "FDENOMINATOR",
                            "FNUMERATOR"
                    ),
                    String.format("FMATERIALID.FNUMBER = '%s' and FMATERIALIDCHILD.FNUMBER = '%s'", kingdeeMaterialNo, materialNo), null, 0, 1);
            if (materialBomQuery.size() == 0) {
                denominator = 1;
                numerator = 1;
            } else {
                denominator = VtuzxUtil.getDouble(materialBomQuery.get(0), "FDENOMINATOR");
                numerator = VtuzxUtil.getDouble(materialBomQuery.get(0), "FNUMERATOR");
            }
        }

        Map<String, Object> materialBoms = new LinkedHashMap<>();
        Long max = 0l;
        double qty = 0d;
        if ("product".equals(type)) {
            max = gcd(Long.parseLong(String.valueOf(Math.round(fQty * 10000))), Long.parseLong(String.valueOf(Math.round(bigCount * 10000))));
        } else {
            double sum = BigDecimal.valueOf((fQty * (numerator / denominator)) / (bigCount / materialCount)).setScale(2, RoundingMode.HALF_UP).doubleValue();
            //(系数 / 系数总和 * 领料总数) / 领料总数 * 领料数
//            double sum = BigDecimal.valueOf((coefficient /materialCount * fQty) / fQty * bigCount).setScale(2, RoundingMode.HALF_UP).doubleValue();
            if (!last) {
                qty = sum;
                double lastCount = VtuzxUtil.getDouble(materialBomPickDetailDoc, "lastCount");
                materialBomPickDetailDoc.append("lastCount", lastCount - qty);
            } else {
                qty = BigDecimal.valueOf(VtuzxUtil.getDouble(materialBomPickDetailDoc, "lastCount")).setScale(2, RoundingMode.HALF_UP).doubleValue();
            }
        }
        //存新分录
        materialBoms.put("FMaterialID2", new VtuzxMap("FNumber", materialNo));
        materialBoms.put("FMaterialType", "1");
        materialBoms.put("FSupplyType", "");
        materialBoms.put("FDosageType", "2");
        if ("product".equals(type)) {
            materialBoms.put("FNumerator", bigCount * 10000 / max);//分子
            materialBoms.put("FDenominator", fQty * 10000 / max);//分母
        } else {
            max = gcd(Long.parseLong(String.valueOf(Math.round(qty * 100))), Long.parseLong(String.valueOf(Math.round(fQty * 100))));
            materialBoms.put("FNumerator", qty * 100 / max);//分子
            materialBoms.put("FDenominator", fQty * 100 / max);//分母
        }
        materialBoms.put("FUnitID2", new VtuzxMap("FNumber", unit));
        materialBoms.put("FFixScrapQty", 0);
        materialBoms.put("FScrapRate", 0);
        materialBoms.put("FNeedDate2", "2022-10-10");
        if ("product".equals(type)) {
            materialBoms.put("FStdQty", bigCount);
            materialBoms.put("FNeedQty2 ", bigCount);
            materialBoms.put("FMustQty", bigCount);
        } else {
            materialBoms.put("FStdQty", qty);
            materialBoms.put("FNeedQty2 ", qty);
            materialBoms.put("FMustQty", qty);
        }
        materialBoms.put("FSupplyOrg", new VtuzxMap("FNumber", "100"));
        materialBoms.put("FIsKeyComponent", false);
        materialBoms.put("FBomId2", new VtuzxMap("FNumber", ""));
        materialBoms.put("FAllowOver", false);
        materialBoms.put("FWorkCalId2", new VtuzxMap("FNumber", ""));
        materialBoms.put("FBaseNumerator", 1);
        materialBoms.put("FReserveType", "");
        materialBoms.put("FBASEDENOMINATOR", 1);
        materialBoms.put("FSMEntryId", 0);
        materialBoms.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
        materialBoms.put("FEntrustPickOrgId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FOperID", 0);
        if (isBatchManage) {
            materialBoms.put("FLot", new VtuzxMap("FNumber", batchNo));
        }
        materialBoms.put("FOffsetTime", 0);
        materialBoms.put("FProcessID", new VtuzxMap("FNumber", ""));
        materialBoms.put("FIssueType", "1");
        if ("product".equals(type)) {
            materialBoms.put("FStockID", new VtuzxMap("FNumber", stockNo));
        } else {
            materialBoms.put("FStockID", new VtuzxMap("FNumber", "0028"));
        }
        materialBoms.put("FSrcTransOrgId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FSrcTransStockId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FNoPickedQty", 0);
        materialBoms.put("FInventoryQty", 0);
        materialBoms.put("FIsSkip", false);
        materialBoms.put("FISMinIssueQty", false);
        materialBoms.put("FIsGetScrap", false);
        materialBoms.put("FPPBomEntryType", "0");
        materialBoms.put("FUPDATERID", new VtuzxMap("FNumber", ""));
        materialBoms.put("FUPDateDate", "2022-10-10");
        materialBoms.put("FOwnerTypeId", "BD_OwnerOrg");
        materialBoms.put("FSupplyMode", "z");
        materialBoms.put("FBaseNoPickedQty", 0);
        materialBoms.put("FIsMrpRun", false);
        materialBoms.put("FSrcPPBOMID", 0);
        materialBoms.put("FSrcPPBOMEntryId", 0);
        materialBoms.put("FStockReadyQty", 0);
        materialBoms.put("FBaseStockReadyQty", 0);
        materialBoms.put("FBaseUnitID1", new VtuzxMap("FNumber", unit));
        materialBoms.put("FReturnNoOkQty", 0);
        materialBoms.put("FMoType1", new VtuzxMap("FNumber", "SCDD03_SYS"));
        materialBoms.put("FOwnerID", new VtuzxMap("FNumber", "100"));
        materialBoms.put("FGroupByOwnerId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FIsExpand", false);
        materialBoms.put("FCheckReturnMtrl", false);
        materialBoms.put("FBaseReturnAppSelQty", 0);
        materialBoms.put("FReturnAppSelQty", 0);
        fMaterialBomEntry.add(materialBoms);

    }

    //修改用料清单BN
    private void ppBomInnerBn(VtuzxKingdeeCloudClient client, Document materialBomPickDetailDoc, VtuzxMap kingdeePrdOrder, double fQty, String taskBillNo, double materialCount, VtuzxMap materialMap, List<Map<String, Object>> fMaterialBomEntry, boolean last) throws Exception {

        Document taskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String type = VtuzxUtil.getString(taskDoc, "type");
        String materialNo = VtuzxUtil.getString(materialBomPickDetailDoc, "materialNo");
        Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
        boolean isBatchManage = VtuzxUtil.getBoolean(materialMap, materialNo);
        String batchNo = VtuzxUtil.getString(materialBomPickDetailDoc, "batchNo");
        String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
        String stockNo = "002";
        double count = 0;
        count = VtuzxUtil.getDouble(materialBomPickDetailDoc, "count");

        double bigCount = BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue();
        double denominator = 0d;
        double numerator = 0d;
        if ("sorting".equals(type)) {
            String kingdeeMaterialNo = VtuzxUtil.getString(kingdeePrdOrder, "kingdeeMaterialNo");
            List<VtuzxMap> materialBomQuery = kingdeeService.query(client, "ENG_BOM", new VtuzxArrayList<>(
                            "FMATERIALID.FNUMBER",
                            "FDENOMINATOR",
                            "FNUMERATOR"
                    ),
                    String.format("FMATERIALID.FNUMBER = '%s' and FMATERIALIDCHILD.FNUMBER = '%s'", kingdeeMaterialNo, materialNo), null, 0, 1);
            if (materialBomQuery.size() == 0) {
                denominator = 1;
                numerator = 1;
            } else {
                denominator = VtuzxUtil.getDouble(materialBomQuery.get(0), "FDENOMINATOR");
                numerator = VtuzxUtil.getDouble(materialBomQuery.get(0), "FNUMERATOR");
            }
        }

        Map<String, Object> materialBoms = new LinkedHashMap<>();
        Long max = 0l;
        double qty = 0d;
        if ("product".equals(type)) {
            max = gcd(Long.parseLong(String.valueOf(Math.round(fQty * 10000))), Long.parseLong(String.valueOf(Math.round(bigCount * 10000))));
        } else {
            double sum = BigDecimal.valueOf((fQty * (numerator / denominator)) / (bigCount / materialCount)).setScale(2, RoundingMode.HALF_UP).doubleValue();
            //(系数 / 系数总和 * 领料总数) / 领料总数 * 领料数
//            double sum = BigDecimal.valueOf((coefficient /materialCount * fQty) / fQty * bigCount).setScale(2, RoundingMode.HALF_UP).doubleValue();
            if (!last) {
                qty = sum;
                double lastCount = VtuzxUtil.getDouble(materialBomPickDetailDoc, "lastCount");
                materialBomPickDetailDoc.append("lastCount", lastCount - qty);
            } else {
                qty = BigDecimal.valueOf(VtuzxUtil.getDouble(materialBomPickDetailDoc, "lastCount")).setScale(2, RoundingMode.HALF_UP).doubleValue();
            }
        }
        //存新分录
        materialBoms.put("FMaterialID2", new VtuzxMap("FNumber", materialNo));
        materialBoms.put("FMaterialType", "1");
        materialBoms.put("FSupplyType", "");
        materialBoms.put("FDosageType", "2");
        if ("product".equals(type)) {
            materialBoms.put("FNumerator", bigCount * 10000 / max);//分子
            materialBoms.put("FDenominator", fQty * 10000 / max);//分母
        } else {
            max = gcd(Long.parseLong(String.valueOf(Math.round(qty * 100))), Long.parseLong(String.valueOf(Math.round(fQty * 100))));
            materialBoms.put("FNumerator", qty * 100 / max);//分子
            materialBoms.put("FDenominator", fQty * 100 / max);//分母
        }
        materialBoms.put("FUnitID2", new VtuzxMap("FNumber", unit));
        materialBoms.put("FFixScrapQty", 0);
        materialBoms.put("FScrapRate", 0);
//        materialBoms.put("FNeedDate2", new Date());
        if ("product".equals(type)) {
            materialBoms.put("FStdQty", bigCount);
            materialBoms.put("FNeedQty2 ", bigCount);
            materialBoms.put("FMustQty", bigCount);
        } else {
            materialBoms.put("FStdQty", qty);
            materialBoms.put("FNeedQty2 ", qty);
            materialBoms.put("FMustQty", qty);
        }
        materialBoms.put("FSupplyOrg", new VtuzxMap("FNumber", "200"));
        materialBoms.put("FIsKeyComponent", false);
        materialBoms.put("FBomId2", new VtuzxMap("FNumber", ""));
        materialBoms.put("FAllowOver", false);
        materialBoms.put("FWorkCalId2", new VtuzxMap("FNumber", ""));
        materialBoms.put("FBaseNumerator", 1);
        materialBoms.put("FReserveType", "");
        materialBoms.put("FBASEDENOMINATOR", 1);
        materialBoms.put("FSMEntryId", 0);
        materialBoms.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
        materialBoms.put("FEntrustPickOrgId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FOperID", 0);
        if (isBatchManage) {
            materialBoms.put("FLot", new VtuzxMap("FNumber", batchNo));
        }
        materialBoms.put("FOffsetTime", 0);
        materialBoms.put("FProcessID", new VtuzxMap("FNumber", ""));
        materialBoms.put("FIssueType", "1");
        materialBoms.put("FStockID", new VtuzxMap("FNumber", stockNo));
        materialBoms.put("FSrcTransOrgId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FSrcTransStockId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FNoPickedQty", 0);
        materialBoms.put("FInventoryQty", 0);
        materialBoms.put("FIsSkip", false);
        materialBoms.put("FISMinIssueQty", false);
        materialBoms.put("FIsGetScrap", false);
        materialBoms.put("FPPBomEntryType", "0");
        materialBoms.put("FUPDATERID", new VtuzxMap("FNumber", ""));
//        materialBoms.put("FUPDateDate", "2022-10-10");
        materialBoms.put("FOwnerTypeId", "BD_OwnerOrg");
        materialBoms.put("FSupplyMode", "z");
        materialBoms.put("FBaseNoPickedQty", 0);
        materialBoms.put("FIsMrpRun", false);
        materialBoms.put("FSrcPPBOMID", 0);
        materialBoms.put("FSrcPPBOMEntryId", 0);
        materialBoms.put("FStockReadyQty", 0);
        materialBoms.put("FBaseStockReadyQty", 0);
        materialBoms.put("FBaseUnitID1", new VtuzxMap("FNumber", unit));
        materialBoms.put("FReturnNoOkQty", 0);
        materialBoms.put("FMoType1", new VtuzxMap("FNumber", "SCDD03_SYS"));
        materialBoms.put("FOwnerID", new VtuzxMap("FNumber", "200"));
        materialBoms.put("FGroupByOwnerId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FIsExpand", false);
        materialBoms.put("FCheckReturnMtrl", false);
        materialBoms.put("FBaseReturnAppSelQty", 0);
        materialBoms.put("FReturnAppSelQty", 0);
        fMaterialBomEntry.add(materialBoms);

    }
    //修改用料清单水带
    private void ppBomInnerSD(VtuzxKingdeeCloudClient client, Document materialBomPickDetailDoc, VtuzxMap kingdeePrdOrder, double fQty, String taskBillNo, double materialCount, VtuzxMap materialMap, List<Map<String, Object>> fMaterialBomEntry, boolean last) throws Exception {

        Document taskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String type = VtuzxUtil.getString(taskDoc, "type");
        String materialNo = VtuzxUtil.getString(materialBomPickDetailDoc, "materialNo");
        Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
        boolean isBatchManage = VtuzxUtil.getBoolean(materialMap, materialNo);
        String batchNo = VtuzxUtil.getString(materialBomPickDetailDoc, "batchNo");
        String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
        String stockNo = VtuzxUtil.getString(materialBomPickDetailDoc, "stockNo");
        double count = VtuzxUtil.getDouble(materialBomPickDetailDoc, "count");
        double coefficient = VtuzxUtil.getDouble(kingdeePrdOrder, "coefficient");

        double bigCount = BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue();

        Map<String, Object> materialBoms = new LinkedHashMap<>();
        int max = 0;
        double qty = 0d;
        if ("product".equals(type)) {
            max = gcd(Integer.parseInt(String.valueOf(Math.round(fQty * 10000))), Integer.parseInt(String.valueOf(Math.round(bigCount * 10000))));
        } else {
//            double sum = BigDecimal.valueOf((fQty * (numerator / denominator)) * (bigCount / materialCount)).setScale(2, RoundingMode.HALF_UP).doubleValue();
            //(系数 / 系数总和 * 领料总数) / 领料总数 * 领料数
            double sum = BigDecimal.valueOf((coefficient / materialCount * fQty) / fQty * bigCount).setScale(2, RoundingMode.HALF_UP).doubleValue();
            if (!last) {
                qty = sum;
                double lastCount = BigDecimal.valueOf(VtuzxUtil.getDouble(materialBomPickDetailDoc, "lastCount")).setScale(2, RoundingMode.HALF_UP).doubleValue();
                //判断剩余的领料数和分配的领料数
                if (lastCount > qty) {
                    materialBomPickDetailDoc.append("lastCount", lastCount - qty);
                } else {
                    materialBomPickDetailDoc.append("lastCount", 0);
                    qty = lastCount;
                }


            } else {
                qty = BigDecimal.valueOf(VtuzxUtil.getDouble(materialBomPickDetailDoc, "lastCount")).setScale(2, RoundingMode.HALF_UP).doubleValue();
            }
        }
        //存新分录
        materialBoms.put("FMaterialID2", new VtuzxMap("FNumber", materialNo));
        materialBoms.put("FMaterialType", "1");
        materialBoms.put("FSupplyType", "");
        materialBoms.put("FDosageType", "2");
        if ("product".equals(type)) {
            materialBoms.put("FNumerator", bigCount * 10000 / max);//分子
            materialBoms.put("FDenominator", fQty * 10000 / max);//分母
        } else {
            max = gcd(Integer.parseInt(String.valueOf(Math.round(qty * 100))), Integer.parseInt(String.valueOf(Math.round(fQty * 100))));
            materialBoms.put("FNumerator", qty * 100 / max);//分子
            materialBoms.put("FDenominator", fQty * 100 / max);//分母
        }
        materialBoms.put("FUnitID2", new VtuzxMap("FNumber", unit));
        materialBoms.put("FFixScrapQty", 0);
        materialBoms.put("FScrapRate", 0);
        materialBoms.put("FNeedDate2", "2022-10-10");
        if ("product".equals(type)) {
            materialBoms.put("FStdQty", bigCount);
            materialBoms.put("FNeedQty2 ", bigCount);
            materialBoms.put("FMustQty", bigCount);
        } else {
            materialBoms.put("FStdQty", qty);
            materialBoms.put("FNeedQty2 ", qty);
            materialBoms.put("FMustQty", qty);
        }
        materialBoms.put("FSupplyOrg", new VtuzxMap("FNumber", "100"));
        materialBoms.put("FIsKeyComponent", false);
        materialBoms.put("FBomId2", new VtuzxMap("FNumber", ""));
        materialBoms.put("FAllowOver", false);
        materialBoms.put("FWorkCalId2", new VtuzxMap("FNumber", ""));
        materialBoms.put("FBaseNumerator", 1);
        materialBoms.put("FReserveType", "");
        materialBoms.put("FBASEDENOMINATOR", 1);
        materialBoms.put("FSMEntryId", 0);
        materialBoms.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
        materialBoms.put("FEntrustPickOrgId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FOperID", 0);
        if (isBatchManage) {
            materialBoms.put("FLot", new VtuzxMap("FNumber", batchNo));
        }
        materialBoms.put("FOffsetTime", 0);
        materialBoms.put("FProcessID", new VtuzxMap("FNumber", ""));
        materialBoms.put("FIssueType", "1");
        if ("product".equals(type)) {
            materialBoms.put("FStockID", new VtuzxMap("FNumber", stockNo));
        } else {
            materialBoms.put("FStockID", new VtuzxMap("FNumber", "0028"));
        }
        materialBoms.put("FSrcTransOrgId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FSrcTransStockId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FNoPickedQty", 0);
        materialBoms.put("FInventoryQty", 0);
        materialBoms.put("FIsSkip", false);
        materialBoms.put("FISMinIssueQty", false);
        materialBoms.put("FIsGetScrap", false);
        materialBoms.put("FPPBomEntryType", "0");
        materialBoms.put("FUPDATERID", new VtuzxMap("FNumber", ""));
        materialBoms.put("FUPDateDate", "2022-10-10");
        materialBoms.put("FOwnerTypeId", "BD_OwnerOrg");
        materialBoms.put("FSupplyMode", "z");
        materialBoms.put("FBaseNoPickedQty", 0);
        materialBoms.put("FIsMrpRun", false);
        materialBoms.put("FSrcPPBOMID", 0);
        materialBoms.put("FSrcPPBOMEntryId", 0);
        materialBoms.put("FStockReadyQty", 0);
        materialBoms.put("FBaseStockReadyQty", 0);
        materialBoms.put("FBaseUnitID1", new VtuzxMap("FNumber", unit));
        materialBoms.put("FReturnNoOkQty", 0);
        materialBoms.put("FMoType1", new VtuzxMap("FNumber", "SCDD03_SYS"));
        materialBoms.put("FOwnerID", new VtuzxMap("FNumber", "100"));
        materialBoms.put("FGroupByOwnerId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FIsExpand", false);
        materialBoms.put("FCheckReturnMtrl", false);
        materialBoms.put("FBaseReturnAppSelQty", 0);
        materialBoms.put("FReturnAppSelQty", 0);
        fMaterialBomEntry.add(materialBoms);

    }

    //修改用料清单水带BN
    private double ppBomInnerSDBn(VtuzxKingdeeCloudClient client, Document materialBomPickDetailDoc, VtuzxMap kingdeePrdOrder, double fQty, String taskBillNo, double materialCount, VtuzxMap materialMap, List<Map<String, Object>> fMaterialBomEntry, boolean last, double noWeightMaterialCount) throws Exception {
        Document taskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String type = VtuzxUtil.getString(taskDoc, "type");
        String materialNo = VtuzxUtil.getString(materialBomPickDetailDoc, "materialNo");
        Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
        boolean isBatchManage = VtuzxUtil.getBoolean(materialMap, materialNo);
        String batchNo = VtuzxUtil.getString(materialBomPickDetailDoc, "batchNo");
        String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
        String stockNo = VtuzxUtil.getString(materialBomPickDetailDoc, "stockNo");
        double count = VtuzxUtil.getDouble(materialBomPickDetailDoc, "count");
        double coefficient = VtuzxUtil.getDouble(kingdeePrdOrder, "coefficient");
        double bigCount = BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue();
        //计算原领料数
        int noWeightMax = 0;
        double noWeightQty = 0d;
        double noWeightCoefficient = VtuzxUtil.getDouble(kingdeePrdOrder, "noWeightCoefficient");
        if ("product".equals(type)) {
            noWeightMax = gcd(Integer.parseInt(String.valueOf(Math.round(fQty * 10000))), Integer.parseInt(String.valueOf(Math.round(bigCount * 10000))));
        } else {
            //(系数(原领料) / 系数总和(原领料) * 领料总数) / 领料总数 * 领料数
            double noWeightSum = BigDecimal.valueOf((noWeightCoefficient / noWeightMaterialCount * fQty) / fQty * bigCount).setScale(2, RoundingMode.HALF_UP).doubleValue();
            if (!last) {
                noWeightQty = noWeightSum;
                double lastNoWeightCount = BigDecimal.valueOf(VtuzxUtil.getDouble(materialBomPickDetailDoc, "lastNoWeightCount")).setScale(2, RoundingMode.HALF_UP).doubleValue();
                //判断剩余的领料数(原领料) 和分配的领料数(原领料)
                if (lastNoWeightCount > noWeightQty) {
                    materialBomPickDetailDoc.append("lastNoWeightCount", lastNoWeightCount - noWeightQty);
                } else {
                    materialBomPickDetailDoc.append("lastNoWeightCount", 0);
                    noWeightQty = lastNoWeightCount;
                }
            } else {
                noWeightQty = BigDecimal.valueOf(VtuzxUtil.getDouble(materialBomPickDetailDoc, "lastNoWeightCount")).setScale(2, RoundingMode.HALF_UP).doubleValue();
            }
        }
        Map<String, Object> materialBoms = new LinkedHashMap<>();
        int max = 0;
        double qty = 0d;
        if ("product".equals(type)) {
            max = gcd(Integer.parseInt(String.valueOf(Math.round(fQty * 10000))), Integer.parseInt(String.valueOf(Math.round(bigCount * 10000))));
        } else {
//            double sum = BigDecimal.valueOf((fQty * (numerator / denominator)) * (bigCount / materialCount)).setScale(2, RoundingMode.HALF_UP).doubleValue();
            //(系数 / 系数总和 * 领料总数) / 领料总数 * 领料数
            double sum = BigDecimal.valueOf((coefficient / materialCount * fQty) / fQty * bigCount).setScale(2, RoundingMode.HALF_UP).doubleValue();
            if (!last) {
                qty = sum;
                double lastCount = BigDecimal.valueOf(VtuzxUtil.getDouble(materialBomPickDetailDoc, "lastCount")).setScale(2, RoundingMode.HALF_UP).doubleValue();
                //判断剩余的领料数和分配的领料数
                if (lastCount > qty) {
                    materialBomPickDetailDoc.append("lastCount", lastCount - qty);
                } else {
                    materialBomPickDetailDoc.append("lastCount", 0);
                    qty = lastCount;
                }


            } else {
                qty = BigDecimal.valueOf(VtuzxUtil.getDouble(materialBomPickDetailDoc, "lastCount")).setScale(2, RoundingMode.HALF_UP).doubleValue();
            }
        }
        //存新分录
        materialBoms.put("FMaterialID2", new VtuzxMap("FNumber", materialNo));
        materialBoms.put("FMaterialType", "1");
        materialBoms.put("FSupplyType", "");
        materialBoms.put("FDosageType", "2");
        if ("product".equals(type)) {
            materialBoms.put("FNumerator", bigCount * 10000 / max);//分子
            materialBoms.put("FDenominator", fQty * 10000 / max);//分母
        } else {
            max = gcd(Integer.parseInt(String.valueOf(Math.round(qty * 100))), Integer.parseInt(String.valueOf(Math.round(fQty * 100))));
            materialBoms.put("FNumerator", qty * 100 / max);//分子
            materialBoms.put("FDenominator", fQty * 100 / max);//分母
        }
        materialBoms.put("FUnitID2", new VtuzxMap("FNumber", unit));
        materialBoms.put("FFixScrapQty", 0);
        materialBoms.put("FScrapRate", 0);
//        materialBoms.put("FNeedDate2", "2022-10-10");
        if ("product".equals(type)) {
            materialBoms.put("FStdQty", bigCount);
            materialBoms.put("FNeedQty2 ", bigCount);
            materialBoms.put("FMustQty", bigCount);
        } else {
            materialBoms.put("FStdQty", qty);
            materialBoms.put("FNeedQty2 ", qty);
            materialBoms.put("FMustQty", qty);
        }
        materialBoms.put("FSupplyOrg", new VtuzxMap("FNumber", "200"));
        materialBoms.put("FIsKeyComponent", false);
        materialBoms.put("FBomId2", new VtuzxMap("FNumber", ""));
        materialBoms.put("FAllowOver", false);
        materialBoms.put("FWorkCalId2", new VtuzxMap("FNumber", ""));
        materialBoms.put("FBaseNumerator", 1);
        materialBoms.put("FReserveType", "");
        materialBoms.put("FBASEDENOMINATOR", 1);
        materialBoms.put("FSMEntryId", 0);
        materialBoms.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
        materialBoms.put("FEntrustPickOrgId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FOperID", 0);
        if (isBatchManage) {
            materialBoms.put("FLot", new VtuzxMap("FNumber", batchNo));
        }
        materialBoms.put("FOffsetTime", 0);
        materialBoms.put("FProcessID", new VtuzxMap("FNumber", ""));
        materialBoms.put("FIssueType", "1");
        if ("product".equals(type)) {
            materialBoms.put("FStockID", new VtuzxMap("FNumber", "stockNo"));
        } else {
            materialBoms.put("FStockID", new VtuzxMap("FNumber", "003"));
        }
        materialBoms.put("FSrcTransOrgId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FSrcTransStockId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FNoPickedQty", 0);
        materialBoms.put("FInventoryQty", 0);
        materialBoms.put("FIsSkip", false);
        materialBoms.put("FISMinIssueQty", false);
        materialBoms.put("FIsGetScrap", false);
        materialBoms.put("FPPBomEntryType", "0");
        materialBoms.put("FUPDATERID", new VtuzxMap("FNumber", ""));
        materialBoms.put("FUPDateDate", "2022-10-10");
        materialBoms.put("FOwnerTypeId", "BD_OwnerOrg");
        materialBoms.put("FSupplyMode", "z");
        materialBoms.put("FBaseNoPickedQty", 0);
        materialBoms.put("FIsMrpRun", false);
        materialBoms.put("FSrcPPBOMID", 0);
        materialBoms.put("FSrcPPBOMEntryId", 0);
        materialBoms.put("FStockReadyQty", 0);
        materialBoms.put("FBaseStockReadyQty", 0);
        materialBoms.put("FBaseUnitID1", new VtuzxMap("FNumber", unit));
        materialBoms.put("FReturnNoOkQty", 0);
        materialBoms.put("FMoType1", new VtuzxMap("FNumber", "SCDD03_SYS"));
        materialBoms.put("FOwnerID", new VtuzxMap("FNumber", "200"));
        materialBoms.put("FGroupByOwnerId", new VtuzxMap("FNumber", ""));
        materialBoms.put("FIsExpand", false);
        materialBoms.put("FCheckReturnMtrl", false);
        materialBoms.put("FBaseReturnAppSelQty", 0);
        materialBoms.put("FReturnAppSelQty", 0);
        fMaterialBomEntry.add(materialBoms);
        return noWeightQty;
    }

    //用料清单存旧分录
    private void materialPickInner(VtuzxMap prdPickOrder, List<Map<String, Object>> fMaterialBomEntry) {
        Map<String, Object> materialBoms = new LinkedHashMap<>();
        String fEntryID = VtuzxUtil.getString(prdPickOrder, "FEntity_FEntryID");
//        double fNeedQty2 = VtuzxUtil.getDouble(prdPickOrder, "FNeedQty2");
//        String fUnitID2_Number = VtuzxUtil.getString(prdPickOrder, "FUnitID2.FNumber");
//        String fMaterialID2_Number = VtuzxUtil.getString(prdPickOrder, "FMaterialID2.FNumber");
        materialBoms.put("FEntryID", fEntryID);
        fMaterialBomEntry.add(materialBoms);
    }


    @Override
    public void syncPrdInStockOrder(ObjectId userId, String name, String billNo, String source, String prdInTime) throws Exception {

        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        boolean success = VtuzxUtil.getBoolean(historyDoc, "success");
//        if (success) {
//            return;
//        }
        Document prdInDoc = prdInDao.findOne(Criteria.where("billNo").is(billNo));
        int boxCount = VtuzxUtil.getInt(prdInDoc, "boxCount");
        if (boxCount == 0) {
            historyDoc.append("prdInStock", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }
        historyDoc.append("billNo", billNo);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("source", source);
        historyDoc.append("data", prdInDoc);
        historyDoc.append("event", "prdInStock");
        try {
            syncPrdInStockOrderInner(historyDoc, prdInTime);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdInStockStock", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }

    }

    @Override
    public void syncPrdInStockOrderBn(ObjectId userId, String name, String billNo, String source, String prdInTime) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        boolean success = VtuzxUtil.getBoolean(historyDoc, "success");
//        if (success) {
//            return;
//        }
        Document prdInDoc = prdInDao.findOne(Criteria.where("billNo").is(billNo));
        /*int boxCount = VtuzxUtil.getInt(prdInDoc, "boxCount");*/
        Iterator<Document> inStockDetailItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        List<Document> validDetails = new ArrayList<>();
        while (inStockDetailItr.hasNext()) {
            Document detail = inStockDetailItr.next();
            String batchNo = VtuzxUtil.getString(detail, "batchNo");
            if (batchNo != null && batchNo.toUpperCase().startsWith("BN")) {
                validDetails.add(detail);
            }
        }
        int validBoxCount = validDetails.size();
        if (validBoxCount == 0) {
            historyDoc.append("prdInStock", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                historyDoc.append("filteredDetails", validDetails);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }
        historyDoc.append("billNo", billNo);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("source", source);
        historyDoc.append("data", prdInDoc);
        historyDoc.append("event", "prdInStock");
        historyDoc.append("filteredDetails", validDetails);
        try {
            syncPrdInStockOrderInnerBn(historyDoc, prdInTime);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdInStockStock", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }

    }

    private void syncPrdInStockOrderInner(Document historyDoc, String prdInTime) throws Exception {
            Document prdIn = VtuzxUtil.getObject(historyDoc, "data");
            String billNo = VtuzxUtil.getString(historyDoc, "billNo");
            Iterator<Document> prdItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
            List<Document> prdList = new ArrayList<>();
            while (prdItr.hasNext()) {
                Document prdDoc = prdItr.next();
                prdList.add(prdDoc);
            }
            int i = 0;
            for (Document prdDoc : prdList) {
                String source = VtuzxUtil.getString(historyDoc, "source");
                String taskBillNo = VtuzxUtil.getString(prdIn, "taskBillNo");
                String createUserName = VtuzxUtil.getString(prdIn, "createUserName");
                String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdDoc, "createTime"));

                VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
                List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                                "FBillNo",
                                "FDate"
                        ),
                        String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 1);

                if (VtuzxUtil.isEmpty(prdOrderQuery)) return;
                String kingdeeBillNo = VtuzxUtil.getString(prdOrderQuery.get(0), "FBillNo");
                String orderDate = VtuzxUtil.getString(prdOrderQuery.get(0), "FDate");
                //用生产订单下推生产入库
                List<String> prdBillNoList = new ArrayList<>();
                prdBillNoList.add(kingdeeBillNo);
                Map<String, Object> prdToInStockMap = new LinkedHashMap<>();
                prdToInStockMap.put("Ids", "");
                prdToInStockMap.put("Numbers", prdBillNoList);
                prdToInStockMap.put("EntryIds", "");
                prdToInStockMap.put("RuleId", "ora_midPRD_PROINSTOCK");
                prdToInStockMap.put("TargetBillTypeId", "");
                prdToInStockMap.put("TargetOrgId", 0);
                prdToInStockMap.put("IsEnableDefaultRule", false);
                prdToInStockMap.put("IsDraftWhenSaveFail", true);
                prdToInStockMap.put("CustomParams", new VtuzxMap());

                historyDoc.append("param", new VtuzxMap());
                VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
                param.append("PRD_MO", prdToInStockMap);
                List<VtuzxMap> prdToInStockList = kingdeeService.push(client, "PRD_MO", prdToInStockMap);
                VtuzxMap prdToInStocks = prdToInStockList.get(0);
                String prdToInStockBillNo = VtuzxUtil.getString(prdToInStocks, "Number");
                String prdToInStockId = VtuzxUtil.getString(prdToInStocks, "Id");
//        kingdeeService.submit(client, "PRD_MO", "0", prdToInStockBillNo);
//        kingdeeService.audit(client, "PRD_MO", "0", prdToInStockBillNo);

                //修改生产入库
                List<VtuzxMap> inStockQuery = kingdeeService.query(client, "PRD_INSTOCK", new VtuzxArrayList<>(
                                "FID",
                                "FBillNo",
                                "FEntity_FEntryID",
                                "FMaterialId.FNumber"
                        ),
                        String.format("FBillNo = '%s'", prdToInStockBillNo), null, 0, 1);
                if (VtuzxUtil.isEmpty(inStockQuery)) return;

                List<Map<String, Object>> prdInStockList = new ArrayList<>();
                Map<String, Object> prdInStockParam = new LinkedHashMap<>();
                Map<String, Object> prdInStockModel = new LinkedHashMap<>();
                for (VtuzxMap inStock : inStockQuery) {
                    Map<String, Object> prdInStockMap = new LinkedHashMap<>();
                    String inStockEntryId = VtuzxUtil.getString(inStock, "FEntity_FEntryID");
                    prdInStockMap.put("FEntryID", inStockEntryId);
                    prdInStockList.add(prdInStockMap);
                }

                //查询生产入库
                List<String> materialNoList = new ArrayList<>();
                List<Document> prdInDetailList = new ArrayList<>();
                List<ObjectId> inStockIdList = new ArrayList<>();
                Iterator<Document> prdInDetailItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
                while (prdInDetailItr.hasNext()) {
                    Document prdInDetailDoc = prdInDetailItr.next();
                    String materialNumber = VtuzxUtil.getString(prdInDetailDoc, "materialNo");
                    materialNoList.add(materialNumber);
                    ObjectId id = VtuzxUtil.getObject(prdInDetailDoc, IVtuzxConst.Key__id);
                    inStockIdList.add(id);
                    prdInDetailList.add(prdInDetailDoc);
                }
                String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
                List<VtuzxMap> materialQuery = kingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
                                "FIsBatchManage",
                                "FNumber"
                        ),
                        String.format("FNumber in (%s)", materialNoCond), null, 0, 1);
                if (VtuzxUtil.isEmpty(materialQuery)) return;

                VtuzxMap materialMap = new VtuzxMap();
                for (VtuzxMap material : materialQuery) {
                    String number = VtuzxUtil.getString(material, "FNumber");
                    boolean isBatchManage = VtuzxUtil.getBoolean(material, "FIsBatchManage");
                    materialMap.append(number, isBatchManage);
                }
                //处理要修改的入库数据

                for (Map<String, Object> prdInStock : prdInStockList) {

                    double dCount = VtuzxUtil.getDouble(prdInDetailList.get(i), "count");
                    String materialNo = VtuzxUtil.getString(prdInDetailList.get(i), "materialNo");
                    boolean isBatchManage = VtuzxUtil.getBoolean(materialMap, materialNo);
                    String dStockNo = VtuzxUtil.getString(prdInDetailList.get(i), "stockNo");
                    String dBatchNo = VtuzxUtil.getString(prdInDetailList.get(i), "batchNo");
                    prdInStock.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
                    prdInStock.put("FMustQty", dCount);
                    prdInStock.put("FRealQty", dCount);
                    prdInStock.put("fStockId", new VtuzxMap("FNumber", dStockNo));
                    if (isBatchManage) {
                        prdInStock.put("FLot", new VtuzxMap("FNumber", dBatchNo));
                    }

                }


                prdInStockModel.put("FID", prdToInStockId);
                if (!"Invalid Date".equals(prdInTime) && !VtuzxUtil.isEmpty(prdInTime)) {
                    prdInStockModel.put("FDate", prdInTime);
                }
                prdInStockModel.put("F_scrkd_ZTRKR", createUserName);
                prdInStockModel.put("F_scrkd_ZTRKSJ", createTime);
                prdInStockModel.put("F_scrkd_ZTDJH", billNo);
                prdInStockModel.put("F_scrkd_SJLY", source);
                //存在先入库后创建任务的情况，先判断日期
                if (createTime.compareTo(orderDate) > 0) {//入库日期大于生产订单日期
                    prdInStockModel.put("FDate", createTime);
                } else {//否则传领料的日期
                    Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(taskBillNo));
                    String pickTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(pickDoc, "createTime"));
                    prdInStockModel.put("FDate", pickTime);
                }

                prdInStockModel.put("FEntity", prdInStockList);


                prdInStockParam.put("NeedUpDateFields", new ArrayList<>());
                prdInStockParam.put("NeedReturnFields", new ArrayList<>());
                prdInStockParam.put("IsDeleteEntry", false);
                prdInStockParam.put("SubSystemId", "");
                prdInStockParam.put("IsVerifyBaseDataField", false);
                prdInStockParam.put("IsEntryBatchFill", true);
                prdInStockParam.put("ValidateFlag", true);
                prdInStockParam.put("NumberSearch", true);
                prdInStockParam.put("InterationFlags", "");
                prdInStockParam.put("Model", prdInStockModel);

                param.append("PRD_INSTOCK", prdInStockParam);
                List<VtuzxMap> inStockList = kingdeeService.save(client, "PRD_INSTOCK", prdInStockParam);

                VtuzxMap prdInMap = inStockList.get(0);
                String inNumber = VtuzxUtil.getString(prdInMap, "Number");
                kingdeeService.submit(client, "PRD_INSTOCK", "0", inNumber);
                kingdeeService.audit(client, "PRD_INSTOCK", "0", inNumber, "STK_InvCheckResult");
                historyDoc.append("kingdeeNumber", inNumber);
                historyDoc.append("prdInStock", true);
                i++;
            }


        //处理要修改的入库数据

//        for (Map<String, Object> prdInStock: prdInStockList) {
//            for (Document prdInDetail: prdInDetailList) {
//                double dCount = VtuzxUtil.getDouble(prdInDetail, "count");
//                String materialNo = VtuzxUtil.getString(prdInDetail, "materialNo");
//                boolean isBatchManage = VtuzxUtil.getBoolean(materialMap, materialNo);
//                String dStockNo = VtuzxUtil.getString(prdInDetail, "stockNo");
//                String dBatchNo = VtuzxUtil.getString(prdInDetail, "batchNo");
//                prdInStock.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
//                prdInStock.put("FMustQty", dCount);
//                prdInStock.put("FRealQty", dCount);
//                prdInStock.put("fStockId", new VtuzxMap("FNumber", dStockNo));
//                if (isBatchManage) {
//                    prdInStock.put("FLot", new VtuzxMap("FNumber", dBatchNo));
//                }
//            }
//        }
//
//        prdInStockModel.put("FID", prdToInStockId);
//        prdInStockModel.put("F_scrkd_ZTRKR", createUserName);
//        prdInStockModel.put("F_scrkd_ZTRKSJ", createTime);
//        prdInStockModel.put("F_scrkd_ZTDJH", billNo);
//        prdInStockModel.put("F_scrkd_SJLY", source);
//        prdInStockModel.put("FEntity", prdInStockList);
//
//        prdInStockParam.put("NeedUpDateFields", new ArrayList<>());
//        prdInStockParam.put("NeedReturnFields", new ArrayList<>());
//        prdInStockParam.put("IsDeleteEntry", false);
//        prdInStockParam.put("SubSystemId", "");
//        prdInStockParam.put("IsVerifyBaseDataField", false);
//        prdInStockParam.put("IsEntryBatchFill", true);
//        prdInStockParam.put("ValidateFlag", true);
//        prdInStockParam.put("NumberSearch", true);
//        prdInStockParam.put("InterationFlags", "");
//        prdInStockParam.put("Model", prdInStockModel);
//
//        param.append("PRD_INSTOCK", prdInStockParam);
//        List<VtuzxMap> inStockList = kingdeeService.save(client, "PRD_INSTOCK", prdInStockParam);
//
//        VtuzxMap prdInMap = inStockList.get(0);
//        String inNumber = VtuzxUtil.getString(prdInMap, "Number");
//        kingdeeService.submit(client, "PRD_INSTOCK", "0", inNumber);
//        kingdeeService.audit(client, "PRD_INSTOCK", "0", inNumber, "STK_InvCheckResult");
//        historyDoc.append("kingdeeNumber", inNumber);
//        historyDoc.append("prdInStock", true);

    }

    private void syncPrdInStockOrderInnerBn(Document historyDoc, String prdInTime) throws Exception {
        Document prdIn = VtuzxUtil.getObject(historyDoc, "data");
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        List<Document> validDetails = VtuzxUtil.getObject(historyDoc, "filteredDetails");
        List<Document> prdList = new ArrayList<>(validDetails);
        /*Iterator<Document> prdItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        List<Document> prdList = new ArrayList<>();
        while (prdItr.hasNext()) {
            Document prdDoc = prdItr.next();
            prdList.add(prdDoc);
        }*/
        int i = 0;
        for (Document prdDoc : prdList) {
            String source = VtuzxUtil.getString(historyDoc, "source");
            String taskBillNo = VtuzxUtil.getString(prdIn, "taskBillNo");
            String createUserName = VtuzxUtil.getString(prdIn, "createUserName");
            String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdDoc, "createTime"));
            VtuzxKingdeeCloudClient client = kingdeeService.loginKingdeeYX();
            List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                            "FBillNo",
                            "FDate"
                    ),
                    String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 1);
            if (VtuzxUtil.isEmpty(prdOrderQuery)) return;
            String kingdeeBillNo = VtuzxUtil.getString(prdOrderQuery.get(0), "FBillNo");
            String orderDate = VtuzxUtil.getString(prdOrderQuery.get(0), "FDate");
            //用生产订单下推生产入库
            List<String> prdBillNoList = new ArrayList<>();
            prdBillNoList.add(kingdeeBillNo);
            Map<String, Object> prdToInStockMap = new LinkedHashMap<>();
            prdToInStockMap.put("Ids", "");
            prdToInStockMap.put("Numbers", prdBillNoList);
            prdToInStockMap.put("EntryIds", "");
            prdToInStockMap.put("RuleId", VtuzxUtil.getString(prdPushRuleDao.findOne(Criteria
                    .where("ruleName").is("MOPushINSTOCK")
                    .and("ruleType").is("product")
                    .and("tokenType").is("kingdee3")
            ), "ruleId"));
            prdToInStockMap.put("TargetBillTypeId", "");
            prdToInStockMap.put("TargetOrgId", 0);
            prdToInStockMap.put("IsEnableDefaultRule", false);
            prdToInStockMap.put("IsDraftWhenSaveFail", true);
            prdToInStockMap.put("CustomParams", new VtuzxMap());
            historyDoc.append("param", new VtuzxMap());
            VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
            param.append("PRD_MO", prdToInStockMap);
            List<VtuzxMap> prdToInStockList = kingdeeService.push(client, "PRD_MO", prdToInStockMap);
            VtuzxMap prdToInStocks = prdToInStockList.get(0);
            String prdToInStockBillNo = VtuzxUtil.getString(prdToInStocks, "Number");
            String prdToInStockId = VtuzxUtil.getString(prdToInStocks, "Id");
            //修改生产入库
            List<VtuzxMap> inStockQuery = kingdeeService.query(client, "PRD_INSTOCK", new VtuzxArrayList<>(
                            "FID",
                            "FBillNo",
                            "FEntity_FEntryID",
                            "FMaterialId.FNumber"
                    ),
                    String.format("FBillNo = '%s'", prdToInStockBillNo), null, 0, 1);
            if (VtuzxUtil.isEmpty(inStockQuery)) return;
            List<Map<String, Object>> prdInStockList = new ArrayList<>();
            Map<String, Object> prdInStockParam = new LinkedHashMap<>();
            Map<String, Object> prdInStockModel = new LinkedHashMap<>();
            for (VtuzxMap inStock : inStockQuery) {
                Map<String, Object> prdInStockMap = new LinkedHashMap<>();
                String inStockEntryId = VtuzxUtil.getString(inStock, "FEntity_FEntryID");
                prdInStockMap.put("FEntryID", inStockEntryId);
                prdInStockList.add(prdInStockMap);
            }
            //查询生产入库
            List<String> materialNoList = new ArrayList<>();
            List<Document> prdInDetailList = new ArrayList<>();
            List<ObjectId> inStockIdList = new ArrayList<>();
            Iterator<Document> prdInDetailItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
            while (prdInDetailItr.hasNext()) {
                Document prdInDetailDoc = prdInDetailItr.next();
                String batchNo = VtuzxUtil.getString(prdInDetailDoc, "batchNo");
                if (batchNo != null && batchNo.toUpperCase().startsWith("BN")) {
                    String materialNumber = VtuzxUtil.getString(prdInDetailDoc, "materialNo");
                    materialNoList.add(materialNumber);
                    ObjectId id = VtuzxUtil.getObject(prdInDetailDoc, IVtuzxConst.Key__id);
                    inStockIdList.add(id);
                    prdInDetailList.add(prdInDetailDoc);
                }
            }
            String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
            List<VtuzxMap> materialQuery = kingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
                            "FNumber",
                            "FIsBatchManage"
                    ),
                    String.format("FNumber in (%s)", materialNoCond), null, 0, 1);
            if (VtuzxUtil.isEmpty(materialQuery)) return;
            VtuzxMap materialMap = new VtuzxMap();
            for (VtuzxMap material : materialQuery) {
                String number = VtuzxUtil.getString(material, "FNumber");
                boolean isBatchManage = VtuzxUtil.getBoolean(material, "FIsBatchManage");
                materialMap.append(number, isBatchManage);
            }
            //处理要修改的入库数据
            for (Map<String, Object> prdInStock : prdInStockList) {
                double dCount = VtuzxUtil.getDouble(prdInDetailList.get(i), "count");
                String materialNo = VtuzxUtil.getString(prdInDetailList.get(i), "materialNo");
                boolean isBatchManage = VtuzxUtil.getBoolean(materialMap, materialNo);
                String dStockNo = VtuzxUtil.getString(prdInDetailList.get(i), "stockNo");
                String dBatchNo = VtuzxUtil.getString(prdInDetailList.get(i), "batchNo");
                prdInStock.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
                prdInStock.put("FMustQty", dCount);
                prdInStock.put("FRealQty", dCount);
                prdInStock.put("fStockId", new VtuzxMap("FNumber", dStockNo));
                if (isBatchManage) {
                    prdInStock.put("FLot", new VtuzxMap("FNumber", dBatchNo));
                } else{
                    prdInStock.put("FLot", new VtuzxMap("FNumber", ""));
                }
                prdInStock.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                /*if(CP_WAREHOUSECODE.contains(dStockNo)){
                    prdInStock.put("FStockId", new VtuzxMap("FNumber", "001"));
                } else{
                    prdInStock.put("FStockId", new VtuzxMap("FNumber", "002"));
                }*/
                //20251014生产成品“委外库”
                prdInStock.put("FStockId", new VtuzxMap("FNumber", "002"));
            }
            prdInStockModel.put("FID", prdToInStockId);
            if (!"Invalid Date".equals(prdInTime) && !VtuzxUtil.isEmpty(prdInTime)) {
                prdInStockModel.put("FDate", prdInTime);
            }
            /*20251015===日期*/
            /*if (!"Invalid Date".equals(prdInTime) && !VtuzxUtil.isEmpty(prdInTime)) {
                prdInStockModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));
            }*/
            prdInStockModel.put("F_scrkd_ZTRKR", createUserName);
            prdInStockModel.put("F_scrkd_ZTRKSJ", createTime);
            prdInStockModel.put("F_scrkd_ZTDJH", billNo);
            prdInStockModel.put("F_scrkd_SJLY", source);
            //存在先入库后创建任务的情况，先判断日期
            if (createTime.compareTo(orderDate) > 0) {//入库日期大于生产订单日期
                prdInStockModel.put("FDate", createTime);
            } else {//否则传领料的日期
                Document pickDoc = materialBomPickDao.findOne(Criteria.where("taskBillNo").is(taskBillNo));
                String pickTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(pickDoc, "createTime"));
                prdInStockModel.put("FDate", pickTime);
            }
            /*20251015===日期*/
            /*prdInStockModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));*/
            prdInStockModel.put("FEntity", prdInStockList);
            prdInStockParam.put("NeedUpDateFields", new ArrayList<>());
            prdInStockParam.put("NeedReturnFields", new ArrayList<>());
            prdInStockParam.put("IsDeleteEntry", false);
            prdInStockParam.put("SubSystemId", "");
            prdInStockParam.put("IsVerifyBaseDataField", false);
            prdInStockParam.put("IsEntryBatchFill", true);
            prdInStockParam.put("ValidateFlag", true);
            prdInStockParam.put("NumberSearch", true);
            prdInStockParam.put("InterationFlags", "");
            prdInStockParam.put("Model", prdInStockModel);
            param.append("PRD_INSTOCK", prdInStockParam);
            List<VtuzxMap> inStockList = kingdeeService.save(client, "PRD_INSTOCK", prdInStockParam);
            VtuzxMap prdInMap = inStockList.get(0);
            String inNumber = VtuzxUtil.getString(prdInMap, "Number");
            kingdeeService.submit(client, "PRD_INSTOCK", "0", inNumber);
            kingdeeService.audit(client, "PRD_INSTOCK", "0", inNumber, "STK_InvCheckResult");
            historyDoc.append("kingdeeNumber", inNumber);
            historyDoc.append("prdInStock", true);
            i++;
        }
    }

    private static int gcd(int a, int b) {
        return (a % b == 0) ? b : gcd(b, a % b);
    }

    private static Long gcd(Long a, Long b) {
        return (a % b == 0) ? b : gcd(b, a % b);
    }

    @Override
    public List<String> syncPrdOrderSorting(ObjectId userId, String name, String billNo, String source, List<Map<String, Object>> boxList, String taskTime) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        boolean success = VtuzxUtil.getBoolean(historyDoc, "success");
//        if (success) {
//            return null;
//        }
        Document prdOrderDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));
        String produceHouseNo = VtuzxUtil.getString(prdOrderDoc, "produceHouseNo");
        String createUserName = VtuzxUtil.getString(prdOrderDoc, "createUserName");
        String auditUserName = VtuzxUtil.getString(prdOrderDoc, "auditUserName");
        Date createTime = VtuzxUtil.getObject(prdOrderDoc, "createTime");
        Date auditTime = VtuzxUtil.getObject(prdOrderDoc, "auditTime");
        String startTime = VtuzxUtil.getString(prdOrderDoc, "startTime");
        String endTime = VtuzxUtil.getString(prdOrderDoc, "endTime");


        List<String> materialNoList = new ArrayList<>();
        double sumCount = 0d;
        for (Map<String, Object> box : boxList) {
            String materialNo = VtuzxUtil.getString(box, "materialNo");
            double count = VtuzxUtil.getDouble(box, "count");
            materialNoList.add(materialNo);
            box.put("startTime", startTime);
            box.put("endTime", endTime);
            box.put("createUserName", createUserName);
            box.put("auditUserName", auditUserName);
            box.put("createTime", createTime);
            box.put("auditTime", auditTime);
            box.put("produceHouseNo", produceHouseNo);
            sumCount += count;
        }

        Iterator<Document> materialItr = materialDao.findList(Criteria.where("fNumber").in(materialNoList), null, 0, 0);
        VtuzxMap materialMap = FastUtil.itr2Map(materialItr, "fNumber");

        try {
            List<String> billNoList = new ArrayList<>();
            for (Map<String, Object> box : boxList) {
                String materialNo = VtuzxUtil.getString(box, "materialNo");
                Document material = VtuzxUtil.getObject(materialMap, materialNo);
                String unitNumber = VtuzxUtil.getString(material, "fBaseUnitIdNumber");
                box.put("unitNumber", unitNumber);
                historyDoc.append("billNo", billNo);
                historyDoc.append("source", source);
                historyDoc.append("userId", userId);
                historyDoc.append("userName", name);
                historyDoc.append("sumCount", sumCount);
                historyDoc.append("type", "sorting");
                historyDoc.append("event", "prdOrder");
                historyDoc.append("data", new Document(box));
                historyDoc.append("taskTime", taskTime);//订单日期
                String prdBillNo = syncPrdOrderInner(historyDoc);
                billNoList.add(prdBillNo);
            }
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
            materialBomPickDao.updateOne(Criteria.where("billNo").is(billNo), new Document("transfer", true));
            return billNoList;
        } catch (Exception e) {
            historyDoc.append("prdOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }

    }

    @Override
    public List<String> syncPrdOrderSortingBn(ObjectId userId, String name, String billNo, String source, List<Map<String, Object>> boxList, String taskTime) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        boolean success = VtuzxUtil.getBoolean(historyDoc, "success");
//        if (success) {
//            return null;
//        }
        Document prdOrderDoc = prdTaskDao.findOne(Criteria.where("billNo").is(billNo));
        String produceHouseNo = VtuzxUtil.getString(prdOrderDoc, "produceHouseNo");
        String createUserName = VtuzxUtil.getString(prdOrderDoc, "createUserName");
        String auditUserName = VtuzxUtil.getString(prdOrderDoc, "auditUserName");
        Date createTime = VtuzxUtil.getObject(prdOrderDoc, "createTime");
        Date auditTime = VtuzxUtil.getObject(prdOrderDoc, "auditTime");
        String startTime = VtuzxUtil.getString(prdOrderDoc, "startTime");
        String endTime = VtuzxUtil.getString(prdOrderDoc, "endTime");


        List<String> materialNoList = new ArrayList<>();
        double sumCount = 0d;
        for (Map<String, Object> box : boxList) {
            String materialNo = VtuzxUtil.getString(box, "materialNo");
            double count = VtuzxUtil.getDouble(box, "count");
            materialNoList.add(materialNo);
            box.put("startTime", startTime);
            box.put("endTime", endTime);
            box.put("createUserName", createUserName);
            box.put("auditUserName", auditUserName);
            box.put("createTime", createTime);
            box.put("auditTime", auditTime);
            box.put("produceHouseNo", produceHouseNo);
            sumCount += count;
        }

        Iterator<Document> materialItr = materialDao.findList(Criteria.where("fNumber").in(materialNoList), null, 0, 0);
        VtuzxMap materialMap = FastUtil.itr2Map(materialItr, "fNumber");

        try {
            List<String> billNoList = new ArrayList<>();
            for (Map<String, Object> box : boxList) {
                String materialNo = VtuzxUtil.getString(box, "materialNo");
                Document material = VtuzxUtil.getObject(materialMap, materialNo);
                String unitNumber = VtuzxUtil.getString(material, "fBaseUnitIdNumber");
                box.put("unitNumber", unitNumber);
                historyDoc.append("billNo", billNo);
                historyDoc.append("source", source);
                historyDoc.append("userId", userId);
                historyDoc.append("userName", name);
                historyDoc.append("sumCount", sumCount);
                historyDoc.append("type", "sorting");
                historyDoc.append("event", "prdOrder");
                historyDoc.append("data", new Document(box));
                historyDoc.append("taskTime", taskTime);//订单日期
                String prdBillNo = syncPrdOrderInnerBn(historyDoc);
                billNoList.add(prdBillNo);
            }
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
            materialBomPickDao.updateOne(Criteria.where("billNo").is(billNo), new Document("transfer", true));
            return billNoList;
        } catch (Exception e) {
            historyDoc.append("prdOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }

    }


    @Override
    public void syncPrdPickOrderSorting(ObjectId userId, String name, String billNo, String source, List<Map<String, Object>> boxList, String pickTime) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        boolean success = VtuzxUtil.getBoolean(historyDoc, "success");
//        if (success) {
//            return;
//        }

        Document prdPickOrderDoc = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
        historyDoc.append("billNo", billNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", prdPickOrderDoc);
        historyDoc.append("boxList", boxList);
        historyDoc.append("event", "prdPick");
        historyDoc.append("pickTime", pickTime);

        try {
            syncPrdPickOrderSortingInner(historyDoc);
            materialBomPickDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$unset", new Document("transfer", 1)));
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdPickOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    @Override
    public void syncPrdPickOrderSortingBn(ObjectId userId, String name, String billNo, String source, List<Map<String, Object>> boxList, String pickTime) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        boolean success = VtuzxUtil.getBoolean(historyDoc, "success");
//        if (success) {
//            return;
//        }
        Iterator<Document> bomPickDocItr = materialBomPickDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        List<Map<String, Object>> validBoxList = new ArrayList<>();
        while (bomPickDocItr.hasNext()) {
            Document bomPickDoc = bomPickDocItr.next();
            String batchNo = VtuzxUtil.getString(bomPickDoc, "batchNo");
            if (batchNo != null && batchNo.toUpperCase().startsWith("BN")) {
                validBoxList.add(bomPickDoc);
            }
        }
        if (validBoxList.isEmpty()) {
            historyDoc.append("prdPickOrder", false).append("message", "无BN批次物料").append("success", true);
            return;
        }
        Document prdPickOrderDoc = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
        historyDoc.append("billNo", billNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", prdPickOrderDoc);
        historyDoc.append("boxList", boxList);
        historyDoc.append("event", "prdPick");
        historyDoc.append("pickTime", pickTime);
        historyDoc.append("filteredBoxList", validBoxList);
        try {
            syncPrdPickOrderSortingInnerBn(historyDoc);
            materialBomPickDao.updateOneRedirect(Criteria.where("billNo").is(billNo), new Document("$unset", new Document("transfer", 1)));
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdPickOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    //分选领料
    private void syncPrdPickOrderSortingInner(Document historyDoc) throws Exception {

        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        Document prdOrder = VtuzxUtil.getObject(historyDoc, "data");
        String source = VtuzxUtil.getString(historyDoc, "source");
        String taskBillNo = VtuzxUtil.getString(prdOrder, "taskBillNo");
        String createName = VtuzxUtil.getString(prdOrder, "createUserName");
        String createTime = VtuzxUtil.formatYmdF(VtuzxUtil.getObject(prdOrder, "createTime"));
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String pickTime = VtuzxUtil.getString(historyDoc, "pickTime");//手动选择的领料日期

        List<String> materialNoList = new ArrayList<>();
        List<Document> bomPickList = new ArrayList<>();
        //领料和补料根据物料和批次先存到一个map集合里，为了计算最终数量
        Map<String, Object> bomMap = new HashMap<>();//k:物料加批次，v:领料和补料里的值
        Iterator<Document> bomPickDocItr = materialBomPickDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (bomPickDocItr.hasNext()) {
            Document bomPickDoc = bomPickDocItr.next();
            String materialNo = VtuzxUtil.getString(bomPickDoc, "materialNo");
            String batchNo = VtuzxUtil.getString(bomPickDoc, "batchNo");
//            bomPickDoc.append("lastCount", VtuzxUtil.getDouble(bomPickDoc, "count"));
            String pickMaterialNo = VtuzxUtil.getString(bomPickDoc, "materialNo");
            materialNoList.add(pickMaterialNo);
            Document bomDoc = (Document) bomMap.get(materialNo + "_" + batchNo);
            if (VtuzxUtil.isEmpty(bomDoc)) {//当前还没有值的话
                bomPickDoc.append("lastCount", VtuzxUtil.getDouble(bomPickDoc, "count"));
                bomMap.put(materialNo + "_" + batchNo, bomPickDoc);
            } else {//有值的话之前数量加上现在数量
                double lastCount = VtuzxUtil.getDouble(bomDoc, "lastCount");
                double count = VtuzxUtil.getDouble(bomDoc, "count");
                bomDoc.replace("lastCount", lastCount + VtuzxUtil.getDouble(bomPickDoc, "count"));
                bomDoc.replace("count", count + VtuzxUtil.getDouble(bomPickDoc, "count"));
                bomMap.put(materialNo + "_" + batchNo, bomDoc);
            }
        }
        Iterator<Document> bomSupplementItr = materialBomSupplementDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo), null, 0, 0);
        while (bomSupplementItr.hasNext()) {
            Document bomSupplementDoc = bomSupplementItr.next();
            String materialNo = VtuzxUtil.getString(bomSupplementDoc, "materialNo");
            String batchNo = VtuzxUtil.getString(bomSupplementDoc, "batchNo");
            String pickMaterialNo = VtuzxUtil.getString(bomSupplementDoc, "materialNo");
            materialNoList.add(pickMaterialNo);
            Document bomDoc = (Document) bomMap.get(materialNo + "_" + batchNo);
            if (VtuzxUtil.isEmpty(bomDoc)) {//当前还没有值的话
                bomSupplementDoc.append("lastCount", VtuzxUtil.getDouble(bomSupplementDoc, "count"));
                bomMap.put(materialNo + "_" + batchNo, bomSupplementDoc);
            } else {//有值的话之前数量加上现在数量
                double lastCount = VtuzxUtil.getDouble(bomDoc, "lastCount");
                bomDoc.replace("lastCount", lastCount + VtuzxUtil.getDouble(bomSupplementDoc, "count"));
                bomDoc.replace("count", lastCount + VtuzxUtil.getDouble(bomSupplementDoc, "count"));
                bomMap.put(materialNo + "_" + batchNo, bomDoc);
            }
        }
        //循环map集合把value放到list集合中
        for (Map.Entry entry : bomMap.entrySet()) {
            Document bomDoc = (Document) entry.getValue();
            bomPickList.add(bomDoc);
        }
        //查看是否有退料
        Iterator<Document> prdInItr = prdInDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo).and("return").is(true), null, 0, 0);
        List<Document> prdInList = new ArrayList<>();
        while (prdInItr.hasNext()) {
            Document prdInDoc = prdInItr.next();
            prdInList.add(prdInDoc);
        }
        if (!VtuzxUtil.isEmpty(prdInList)) {
            for (Document bomDoc : bomPickList) {
                String materialNo = VtuzxUtil.getString(bomDoc, "materialNo");
                String batchNo = VtuzxUtil.getString(bomDoc, "batchNo");
                double lastCount = VtuzxUtil.getDouble(bomDoc, "lastCount");
                double count = VtuzxUtil.getDouble(bomDoc, "count");
                for (Document returnDoc : prdInList) {
                    String returnMaterialNo = VtuzxUtil.getString(returnDoc, "materialNo");
                    String returnBatchNo = VtuzxUtil.getString(returnDoc, "batchNo");
                    double returnCount = VtuzxUtil.getDouble(returnDoc, "count");
                    if (materialNo.equals(returnMaterialNo) && batchNo.equals(returnBatchNo)) {
                        bomDoc.replace("lastCount", lastCount - returnCount);
                        bomDoc.replace("count", count - returnCount);
                        lastCount = lastCount - returnCount;
                        count = count - returnCount;
                    }
                }
            }
        }

        String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
//        String fatherMaterialNoCond = StringUtils.collectionToDelimitedString(fatherMaterialNoList, ",", "'", "'");
        List<VtuzxMap> materialQuery = kingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
                        "FIsBatchManage",
                        "FNumber"
                ),
                String.format("FNumber in (%s)", materialNoCond), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialQuery)) return;

        VtuzxMap materialMap = new VtuzxMap();
        for (VtuzxMap material : materialQuery) {
            String number = VtuzxUtil.getString(material, "FNumber");
            boolean isBatchManage = VtuzxUtil.getBoolean(material, "FIsBatchManage");
            materialMap.append(number, isBatchManage);
        }

        List<VtuzxMap> inventoryQuery = kingdeeService.query(client, "STK_Inventory", new VtuzxArrayList<>(
                        "FLot.FNumber",
                        "FMaterialId.FNumber",
                        "FStockId.FNumber",
                        "FBaseQty"
                ),
                String.format("FMaterialId.FNumber in (%s) and FBaseQty != 0", materialNoCond), null, 0, 0);

        //金蝶即时库存如果查到匹配的物料
        List<Document> depDocList = new ArrayList<>();
        for (Map<String, Object> bomPick : bomPickList) {
            boolean no = false;
            String materialNo = VtuzxUtil.getString(bomPick, "materialNo");
            String batchNo = VtuzxUtil.getString(bomPick, "batchNo");
            String stockNo = VtuzxUtil.getString(bomPick, "stockNo");
            double count = VtuzxUtil.getDouble(bomPick, "count");
            for (VtuzxMap inventory : inventoryQuery) {
                String fMaterialId_FNumber = VtuzxUtil.getString(inventory, "FMaterialId.FNumber");
                String fLot_FNumber = VtuzxUtil.getString(inventory, "FLot.FNumber");
                String fStockId_FNumber = VtuzxUtil.getString(inventory, "FStockId.FNumber");
                double qty = VtuzxUtil.getDouble(inventory, "FBaseQty");
                if (materialNo.equals(fMaterialId_FNumber) && batchNo.equals(fLot_FNumber) && stockNo.equals(fStockId_FNumber)) {
                    no = true;
                    if (qty < count) {
                        Document document = new Document("materialNo", materialNo)
                                .append("batchNo", batchNo)
                                .append("stockNo", stockNo)
                                .append("count", count - qty);
                        depDocList.add(document);
                    }
                }
            }
            if (!no) {
                depDocList.add(new Document("materialNo", materialNo)
                        .append("batchNo", batchNo)
                        .append("stockNo", stockNo)
                        .append("count", count));
            }
        }
        if (depDocList.size() != 0) {
            otherInInner(client, depDocList, null, billNo, param);
        }


        //查生产订单
        List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                        "FBillNo",
                        "FQty",
                        "F_scdd_ZTDJH",
                        "FMaterialId.FNumber",
                        "FDate"
                ),
                String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 0);

        List<VtuzxMap> kingdeeBillNoList = new ArrayList<>();
        if (VtuzxUtil.isEmpty(prdOrderQuery)) return;
        String orderDate = prdOrderQuery.get(0).getString("FDate");
        List<String> billNoList = new ArrayList<>();//存储生产订单号用来查询用料清单
        for (VtuzxMap prdOrderMap : prdOrderQuery) {
            VtuzxMap map = new VtuzxMap();
            String kingdeeBillNo = VtuzxUtil.getString(prdOrderMap, "FBillNo");
            double fQty = VtuzxUtil.getDouble(prdOrderMap, "FQty");
            String kingdeeMaterialNo = VtuzxUtil.getString(prdOrderMap, "FMaterialId.FNumber");
            map.append("fQty", fQty).append("kingdeeBillNo", kingdeeBillNo).append("kingdeeMaterialNo", kingdeeMaterialNo);
            kingdeeBillNoList.add(map);
            if (!billNoList.contains(kingdeeBillNo)) {
                billNoList.add(kingdeeBillNo);
            }
        }
        double materialCount = 0d; //每个产成品按照比例求出所需子项物料系数的和
        //计算用料清单分子分母(所有分选都从物料清单查询)
        List<VtuzxMap> bomQuery = kingdeeService.query(client, "ENG_BOM", new VtuzxArrayList<>(
                        "FMATERIALID.FNUMBER",
                        "FMATERIALIDCHILD.FNUMBER",
                        "FDENOMINATOR",
                        "FNUMERATOR"
                ),
                String.format("FMATERIALIDCHILD.FNUMBER in (%s)", materialNoCond), null, 0, 0);

        if (VtuzxUtil.isEmpty(bomQuery)) {
            throw new VtuzxException(String.format("[%s]的bom不存在", materialNoCond));
        }
        Map<String, Object> bomQueryMap = new HashMap<>();//key父项物料编码  val;分子 分母

        for (VtuzxMap bom : bomQuery) {
            String materialNo = VtuzxUtil.getString(bom, "FMATERIALID.FNUMBER");//物料编号
            double denominator = VtuzxUtil.getDouble(bom, "FDENOMINATOR");//分母
            double numerator = VtuzxUtil.getDouble(bom, "FNUMERATOR");//分子
            Map<String, Object> data = VtuzxUtil.getObject(bomQueryMap, materialNo);
            //无需判断当前父项物料是否在map中有分子分母的信息，直接添加 有的话就覆盖
            Map<String, Object> numMap = new HashMap<>();
            numMap.put("denominator", denominator);
            numMap.put("numerator", numerator);
            bomQueryMap.put(materialNo, numMap);


        }
        //如果当前物料没有bom的话默认分子分母都是1
        for (VtuzxMap kingdeePrdOrder : kingdeeBillNoList) {
            String kingdeeMaterialNo = VtuzxUtil.getString(kingdeePrdOrder, "kingdeeMaterialNo"); //物料编号
            double kingdeeQty = VtuzxUtil.getDouble(kingdeePrdOrder, "fQty");
            Map<String, Object> numMap = VtuzxUtil.getObject(bomQueryMap, kingdeeMaterialNo);
            if (!VtuzxUtil.isEmpty(numMap)) {//如果当前物料有分子分母正常计算系数，没有的话默认分子分母是1
                double denominator = VtuzxUtil.getDouble(numMap, "denominator");//分母
                double numerator = VtuzxUtil.getDouble(numMap, "numerator");//分子
                double coefficient = kingdeeQty * numerator / denominator;
                //总的系数
                materialCount += coefficient;
                kingdeePrdOrder.append("coefficient", coefficient);
            } else {
                double denominator = 1;//分母
                double numerator = 1;//分子
                double coefficient = kingdeeQty * numerator / denominator;
                //总的系数
                materialCount += coefficient;
                kingdeePrdOrder.append("coefficient", coefficient);
            }
        }

//        for (VtuzxMap kingdeePrdOrder: kingdeeBillNoList) {
//            String kingdeeMaterialNo = VtuzxUtil.getString(kingdeePrdOrder, "kingdeeMaterialNo"); //物料编号
//            double kingdeeQty = VtuzxUtil.getDouble(kingdeePrdOrder, "fQty");
//            for (VtuzxMap bom : bomQuery){
//                String materialNo = VtuzxUtil.getString(bom,"FMATERIALID.FNUMBER");//物料编号
//                double denominator = VtuzxUtil.getDouble(bom, "FDENOMINATOR");//分母
//                double numerator = VtuzxUtil.getDouble(bom, "FNUMERATOR");//分子
//                if(kingdeeMaterialNo.equals(materialNo)){
//                    //计算每个订单的系数(订单数量 * 分子 / 分母)
//                    double coefficient = kingdeeQty * numerator / denominator;
//                    //总的系数
//                    materialCount += coefficient;
//                    kingdeePrdOrder.append("coefficient",coefficient);
//                    break;
//                }
//            }
//            }
//        } else {
//            //查询生产用料清单(水带)
//            String bomNoCond = StringUtils.collectionToDelimitedString(billNoList, ",", "'", "'");
//            List<VtuzxMap> bomList = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
//                            "FMOBillNO",//生产订单号
//                            "FNumerator",//分子
//                            "FDenominator"//分母
//
//                    ),
//                    String.format("FMOBillNO in (%s)", bomNoCond), null, 0, 0);
//            for (VtuzxMap kingdeePrdOrder: kingdeeBillNoList) {
//                String kingdeeBillNo = VtuzxUtil.getString(kingdeePrdOrder, "kingdeeBillNo"); //生产订单号
//                double kingdeeQty = VtuzxUtil.getDouble(kingdeePrdOrder, "fQty");
//                for (VtuzxMap bom : bomList){
//                    String FMOBillNO = VtuzxUtil.getString(bom,"FMOBillNO");//生产订单号
//                    double denominator = VtuzxUtil.getDouble(bom, "FDenominator");//分母
//                    double numerator = VtuzxUtil.getDouble(bom, "FNumerator");//分子
//                    if(kingdeeBillNo.equals(FMOBillNO)){
//                        //计算每个订单的系数(订单数量 * 分子 / 分母)
//                        double coefficient = kingdeeQty * numerator / denominator;
//                        //总的系数
//                        materialCount += coefficient;
//                        kingdeePrdOrder.append("coefficient",coefficient);
//                        break;
//                    }
//                }
//
//            }
//        }


        materialCount = BigDecimal.valueOf(materialCount).setScale(2, RoundingMode.HALF_UP).doubleValue();
        //循环全部生产订单
        int size = kingdeeBillNoList.size();
        for (VtuzxMap kingdeeBillNoMap : kingdeeBillNoList) {
            String kingdeeBillNo = VtuzxUtil.getString(kingdeeBillNoMap, "kingdeeBillNo");
            double fQty = VtuzxUtil.getDouble(kingdeeBillNoMap, "fQty");
            List<Map<String, Object>> fMaterialBomEntry = new ArrayList<>();

            List<VtuzxMap> materialBomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                            "FID",
                            "FBillNo",
                            "FMOBillNO",
                            "FMaterialID2.FNumber",
                            "FUnitID2.FNumber",
                            "FNeedQty2",
                            "FEntity_FEntryID"
                    ),
                    String.format("FMOBillNO = '%s'", kingdeeBillNo), null, 0, 0);
            if (VtuzxUtil.isEmpty(materialBomQuery)) return;
            String fid = VtuzxUtil.getString(materialBomQuery.get(0), "FID");
            String entryId = VtuzxUtil.getString(materialBomQuery.get(0), "FEntity_FEntryID");

            //留一个原单据的分录
            materialPickInner(materialBomQuery.get(0), fMaterialBomEntry);

            boolean last = false;
            size--;
            if (size == 0) {
                last = true;
            }
            //fQty 生产订单数 materialCount 同一billNo生产订单下的数量*（分子/分母）的总和
            for (Document bomPickDoc : bomPickList) {
                double count = VtuzxUtil.getDouble(bomPickDoc,"count");
                if (count == 0){
                    continue;
                }
                ppBomInnerSD(client, bomPickDoc, kingdeeBillNoMap, fQty, taskBillNo, materialCount, materialMap, fMaterialBomEntry, last);
            }

            Map<String, Object> prdPickOrderParam = new LinkedHashMap<>();
            Map<String, Object> prdPickOrderModel = new LinkedHashMap<>();
            prdPickOrderModel.put("FID", fid);
            prdPickOrderModel.put("FEntity", fMaterialBomEntry);

            prdPickOrderParam.put("NeedUpDateFields", new ArrayList<>());
            prdPickOrderParam.put("NeedReturnFields", new ArrayList<>());
            prdPickOrderParam.put("IsDeleteEntry", true);
            prdPickOrderParam.put("SubSystemId", "");
            prdPickOrderParam.put("IsVerifyBaseDataField", true);
            prdPickOrderParam.put("IsEntryBatchFill", false);
            prdPickOrderParam.put("ValidateFlag", true);
            prdPickOrderParam.put("NumberSearch", true);
            prdPickOrderParam.put("InterationFlags", "");
            prdPickOrderParam.put("Model", prdPickOrderModel);
            param.append("PRD_PPBOM", prdPickOrderParam);

            List<VtuzxMap> prdPPBomList = kingdeeService.save(client, "PRD_PPBOM", prdPickOrderParam);
            VtuzxMap stkOutStockMap = prdPPBomList.get(0);
            String number = VtuzxUtil.getString(stkOutStockMap, "Number");

            //查新增后的分录id
            List<VtuzxMap> materialBomTwoQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                            "FID",
                            "FBillNo",
                            "FMOBillNO",
                            "FMaterialID2.FNumber",
                            "FUnitID2.FNumber",
                            "FNeedQty2",
                            "FEntity_FEntryID"
                    ),
                    String.format("FBillNo = '%s'", number), null, 0, 0);

            if (VtuzxUtil.isEmpty(materialBomTwoQuery)) return;

            List<Map<String, Object>> entryIdList = new ArrayList<>();
            for (VtuzxMap materialBomTwo : materialBomTwoQuery) {
                Map<String, Object> map = new LinkedHashMap<>();
                String fEntryID = VtuzxUtil.getString(materialBomTwo, "FEntity_FEntryID");
                if (!fEntryID.equals(entryId)) {
                    map.put("FEntryID", fEntryID);
                    entryIdList.add(map);
                }
            }

            Map<String, Object> prdPickOrderTwoParam = new LinkedHashMap<>();
            Map<String, Object> prdPickOrderTwoModel = new LinkedHashMap<>();

            prdPickOrderTwoModel.put("FID", fid);
            prdPickOrderTwoModel.put("FEntity", entryIdList);

            prdPickOrderTwoParam.put("NeedUpDateFields", new ArrayList<>());
            prdPickOrderTwoParam.put("NeedReturnFields", new ArrayList<>());
            prdPickOrderTwoParam.put("IsDeleteEntry", true);
            prdPickOrderTwoParam.put("SubSystemId", "");
            prdPickOrderTwoParam.put("IsVerifyBaseDataField", true);
            prdPickOrderTwoParam.put("IsEntryBatchFill", false);
            prdPickOrderTwoParam.put("ValidateFlag", true);
            prdPickOrderTwoParam.put("NumberSearch", true);
            prdPickOrderTwoParam.put("InterationFlags", "");
            prdPickOrderTwoParam.put("Model", prdPickOrderTwoModel);
            param.append("PRD_PPBOM", prdPickOrderTwoParam);
            String bomNumber = "";
            try {
                List<VtuzxMap> prdPPBomsList = kingdeeService.save(client, "PRD_PPBOM", prdPickOrderTwoParam);
                VtuzxMap prdPPBomsMap = prdPPBomsList.get(0);
                bomNumber = VtuzxUtil.getString(prdPPBomsMap, "Number");
                kingdeeService.submit(client, "PRD_PPBOM", "0", bomNumber);
                kingdeeService.audit(client, "PRD_PPBOM", "0", bomNumber, "STK_InvCheckResult");
            } catch (Exception e){
                _logger.info(e.getMessage());

            }

            //生产订单执行至开工
            kingdeeService.toRelease(client, "PRD_MO", "ToStart", "0", kingdeeBillNo);
            //修改生产订单的下达日期
            try {
                kingdeeService.orderUpdate(client, "PRD_MO", kingdeeBillNo, orderDate);
            } catch (Exception e) {
                _logger.info(e.getMessage());
            }
//            String kingdeeMaterialNo = VtuzxUtil.getString(kingdeeBillNoMap,"kingdeeMaterialNo");


            //用料清单下推生产领料
            List<String> bomNumberList = new ArrayList<>();
            bomNumberList.add(bomNumber);
            Map<String, Object> bomToPickMap = new LinkedHashMap<>();
            bomToPickMap.put("Ids", "");
            bomToPickMap.put("Numbers", bomNumberList);
            bomToPickMap.put("EntryIds", "");
            bomToPickMap.put("RuleId", "ora_sorPRD_PROPICK");
            bomToPickMap.put("TargetBillTypeId", "");
            bomToPickMap.put("TargetOrgId", 0);
            bomToPickMap.put("IsEnableDefaultRule", false);
            bomToPickMap.put("IsDraftWhenSaveFail", false);
            bomToPickMap.put("CustomParams", new VtuzxMap());
            param.append("PRD_PPBOM", bomToPickMap);
            List<VtuzxMap> pickBillList = kingdeeService.push(client, "PRD_PPBOM", bomToPickMap);
            VtuzxMap pickBillMap = pickBillList.get(0);
            String kingdeePickBillNo = VtuzxUtil.getString(pickBillMap, "Number");
            String id = VtuzxUtil.getString(pickBillMap, "Id");

            Map<String, Object> updatePickParam = new LinkedHashMap<>();
            Map<String, Object> updatePickModel = new LinkedHashMap<>();

            updatePickModel.put("FID", id);
            if (!"Invalid Date".equals(pickTime)) {
                updatePickModel.put("FDate", pickTime);//分选领料单的单据日期
            } else {
                updatePickModel.put("FDate", createTime);//分选领料单的单据日期
            }

            updatePickModel.put("F_sclld_ZTLLR", createName);
            updatePickModel.put("F_sclld_ZTDJH", billNo);
            updatePickModel.put("F_sclld_SJLY", source);
            updatePickModel.put("F_sclld_ZTLLSJ", createTime);


            updatePickParam.put("NeedUpDateFields", new ArrayList<>());
            updatePickParam.put("NeedReturnFields", new ArrayList<>());
            updatePickParam.put("IsDeleteEntry", true);
            updatePickParam.put("SubSystemId", "");
            updatePickParam.put("IsVerifyBaseDataField", true);
            updatePickParam.put("IsEntryBatchFill", false);
            updatePickParam.put("ValidateFlag", true);
            updatePickParam.put("NumberSearch", true);
            updatePickParam.put("InterationFlags", "");
            updatePickParam.put("Model", updatePickModel);

            param.append("PRD_PickMtrl", updatePickParam);
            try {
                kingdeeService.save(client, "PRD_PickMtrl", updatePickParam);
                kingdeeService.submit(client, "PRD_PickMtrl", "0", kingdeePickBillNo);
                kingdeeService.audit(client, "PRD_PickMtrl", "0", kingdeePickBillNo, "STK_InvCheckResult");
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }

            historyDoc.append("kingdeeNumber", kingdeePickBillNo);
            historyDoc.append("prdPickOrder", true);

        }
    }

    //分选领料BN
    private void syncPrdPickOrderSortingInnerBn(Document historyDoc) throws Exception {
        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdeeYX();
        Document prdOrder = VtuzxUtil.getObject(historyDoc, "data");
        String source = VtuzxUtil.getString(historyDoc, "source");
        String taskBillNo = VtuzxUtil.getString(prdOrder, "taskBillNo");
        String createName = VtuzxUtil.getString(prdOrder, "createUserName");
        String createTime = VtuzxUtil.formatYmdF(VtuzxUtil.getObject(prdOrder, "createTime"));
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String pickTime = VtuzxUtil.getString(historyDoc, "pickTime");//手动选择的领料日期
        List<String> materialNoList = new ArrayList<>();
        List<Document> bomPickList = new ArrayList<>();
        //领料和补料根据物料和批次先存到一个map集合里，为了计算最终数量
        Map<String, Object> bomMap = new HashMap<>();//k:物料加批次，v:领料和补料里的值
        Iterator<Document> bomPickDocItr = materialBomPickDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (bomPickDocItr.hasNext()) {
            Document bomPickDoc = bomPickDocItr.next();
            String materialNo = VtuzxUtil.getString(bomPickDoc, "materialNo");
            String batchNo = VtuzxUtil.getString(bomPickDoc, "batchNo");
            if (batchNo != null && batchNo.toUpperCase().startsWith("BN")) {
//            bomPickDoc.append("lastCount", VtuzxUtil.getDouble(bomPickDoc, "count"));
                String pickMaterialNo = VtuzxUtil.getString(bomPickDoc, "materialNo");
                materialNoList.add(pickMaterialNo);
                Document bomDoc = (Document) bomMap.get(materialNo + "_" + batchNo);
                if (VtuzxUtil.isEmpty(bomDoc)) {//当前还没有值的话
                    bomPickDoc.append("lastCount", VtuzxUtil.getDouble(bomPickDoc, "count"));
                    bomMap.put(materialNo + "_" + batchNo, bomPickDoc);
                } else {//有值的话之前数量加上现在数量
                    double lastCount = VtuzxUtil.getDouble(bomDoc, "lastCount");
                    double count = VtuzxUtil.getDouble(bomDoc, "count");
                    bomDoc.replace("lastCount", lastCount + VtuzxUtil.getDouble(bomPickDoc, "count"));
                    bomDoc.replace("count", count + VtuzxUtil.getDouble(bomPickDoc, "count"));
                    bomMap.put(materialNo + "_" + batchNo, bomDoc);
                }
            }
        }
        Iterator<Document> bomSupplementItr = materialBomSupplementDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo), null, 0, 0);
        while (bomSupplementItr.hasNext()) {
            Document bomSupplementDoc = bomSupplementItr.next();
            String materialNo = VtuzxUtil.getString(bomSupplementDoc, "materialNo");
            String batchNo = VtuzxUtil.getString(bomSupplementDoc, "batchNo");
            if (batchNo != null && batchNo.toUpperCase().startsWith("BN")) {
                String pickMaterialNo = VtuzxUtil.getString(bomSupplementDoc, "materialNo");
                materialNoList.add(pickMaterialNo);
                Document bomDoc = (Document) bomMap.get(materialNo + "_" + batchNo);
                if (VtuzxUtil.isEmpty(bomDoc)) {//当前还没有值的话
                    bomSupplementDoc.append("lastCount", VtuzxUtil.getDouble(bomSupplementDoc, "count"));
                    bomMap.put(materialNo + "_" + batchNo, bomSupplementDoc);
                } else {//有值的话之前数量加上现在数量
                    double lastCount = VtuzxUtil.getDouble(bomDoc, "lastCount");
                    bomDoc.replace("lastCount", lastCount + VtuzxUtil.getDouble(bomSupplementDoc, "count"));
                    bomDoc.replace("count", lastCount + VtuzxUtil.getDouble(bomSupplementDoc, "count"));
                    bomMap.put(materialNo + "_" + batchNo, bomDoc);
                }
            }
        }
        //循环map集合把value放到list集合中
        for (Map.Entry entry : bomMap.entrySet()) {
            Document bomDoc = (Document) entry.getValue();
            bomPickList.add(bomDoc);
        }
        //查看是否有退料
        Iterator<Document> prdInItr = prdInDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo).and("return").is(true), null, 0, 0);
        List<Document> prdInList = new ArrayList<>();
        while (prdInItr.hasNext()) {
            Document prdInDoc = prdInItr.next();
            prdInList.add(prdInDoc);
        }
        if (!VtuzxUtil.isEmpty(prdInList)) {
            for (Document bomDoc : bomPickList) {
                String materialNo = VtuzxUtil.getString(bomDoc, "materialNo");
                String batchNo = VtuzxUtil.getString(bomDoc, "batchNo");
                double lastCount = VtuzxUtil.getDouble(bomDoc, "lastCount");
                double count = VtuzxUtil.getDouble(bomDoc, "count");
                for (Document returnDoc : prdInList) {
                    String returnMaterialNo = VtuzxUtil.getString(returnDoc, "materialNo");
                    String returnBatchNo = VtuzxUtil.getString(returnDoc, "batchNo");
                    double returnCount = VtuzxUtil.getDouble(returnDoc, "count");
                    if (materialNo.equals(returnMaterialNo) && batchNo.equals(returnBatchNo)) {
                        bomDoc.replace("lastCount", lastCount - returnCount);
                        bomDoc.replace("count", count - returnCount);
                        lastCount = lastCount - returnCount;
                        count = count - returnCount;
                    }
                }
            }
        }
        String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
//        String fatherMaterialNoCond = StringUtils.collectionToDelimitedString(fatherMaterialNoList, ",", "'", "'");
        List<VtuzxMap> materialNoQuery = kingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
                        "FIsBatchManage",
                        "FNumber"
                ),
                String.format("FNumber in (%s)", materialNoCond), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialNoQuery)) return;
        VtuzxMap materialMap = new VtuzxMap();
        for (VtuzxMap material : materialNoQuery) {
            String number = VtuzxUtil.getString(material, "FNumber");
            boolean isBatchManage = VtuzxUtil.getBoolean(material, "FIsBatchManage");
            materialMap.append(number, isBatchManage);
        }
        List<VtuzxMap> inventoryQuery = kingdeeService.query(client, "STK_Inventory", new VtuzxArrayList<>(
                        "FLot.FNumber",
                        "FMaterialId.FNumber",
                        "FStockId.FNumber",
                        "FBaseQty"
                ),
                String.format("FMaterialId.FNumber in (%s) and FBaseQty != 0", materialNoCond), null, 0, 0);
        //金蝶即时库存如果查到匹配的物料
        List<Document> depDocList = new ArrayList<>();
        for (Map<String, Object> bomPick : bomPickList) {
            boolean no = false;
            String materialNo = VtuzxUtil.getString(bomPick, "materialNo");
            String batchNo = VtuzxUtil.getString(bomPick, "batchNo");
            String stockNo = VtuzxUtil.getString(bomPick, "stockNo");
            double count = VtuzxUtil.getDouble(bomPick, "count");
            for (VtuzxMap inventory : inventoryQuery) {
                String fMaterialId_FNumber = VtuzxUtil.getString(inventory, "FMaterialId.FNumber");
                String fLot_FNumber = VtuzxUtil.getString(inventory, "FLot.FNumber");
                String fStockId_FNumber = VtuzxUtil.getString(inventory, "FStockId.FNumber");
                double qty = VtuzxUtil.getDouble(inventory, "FBaseQty");
                if (materialNo.equals(fMaterialId_FNumber) && batchNo.equals(fLot_FNumber) && stockNo.equals(fStockId_FNumber)) {
                    no = true;
                    if (qty < count) {
                        Document document = new Document("materialNo", materialNo)
                                .append("batchNo", batchNo)
                                .append("stockNo", stockNo)
                                .append("count", count - qty);
                        depDocList.add(document);
                    }
                }
            }
            if (!no) {
                depDocList.add(new Document("materialNo", materialNo)
                        .append("batchNo", batchNo)
                        .append("stockNo", stockNo)
                        .append("count", count));
            }
        }
        if (depDocList.size() != 0) {
            otherInInnerBn(client, depDocList, null, billNo, param);
        }
        //查生产订单
        List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                        "FBillNo",
                        "FQty",
                        "F_scdd_ZTDJH",
                        "FMaterialId.FNumber",
                        "FDate"
                ),
                String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 0);
        List<VtuzxMap> kingdeeBillNoList = new ArrayList<>();
        if (VtuzxUtil.isEmpty(prdOrderQuery)) return;
        String orderDate = prdOrderQuery.get(0).getString("FDate");
        List<String> billNoList = new ArrayList<>();//存储生产订单号用来查询用料清单
        for (VtuzxMap prdOrderMap : prdOrderQuery) {
            VtuzxMap map = new VtuzxMap();
            String kingdeeBillNo = VtuzxUtil.getString(prdOrderMap, "FBillNo");
            double fQty = VtuzxUtil.getDouble(prdOrderMap, "FQty");
            String kingdeeMaterialNo = VtuzxUtil.getString(prdOrderMap, "FMaterialId.FNumber");
            map.append("fQty", fQty).append("kingdeeBillNo", kingdeeBillNo).append("kingdeeMaterialNo", kingdeeMaterialNo);
            kingdeeBillNoList.add(map);
            if (!billNoList.contains(kingdeeBillNo)) {
                billNoList.add(kingdeeBillNo);
            }
        }
        double materialCount = 0d; //每个产成品按照比例求出所需子项物料系数的和
        double noWeightMaterialCount = 0d; //每个产成品按照比例求出所需子项物料系数的和(原领料数)
        //计算用料清单分子分母(所有分选都从物料清单查询)
        List<VtuzxMap> bomQuery = kingdeeService.query(client, "ENG_BOM", new VtuzxArrayList<>(
                        "FMATERIALID.FNUMBER",
                        "FMATERIALIDCHILD.FNUMBER",
                        "FDENOMINATOR",
                        "FNUMERATOR"
                ),
                String.format("FMATERIALIDCHILD.FNUMBER in (%s)", materialNoCond), null, 0, 0);
        if (VtuzxUtil.isEmpty(bomQuery)) {
            throw new VtuzxException(String.format("[%s]的bom不存在", materialNoCond));
        }
        Map<String, Object> bomQueryMap = new HashMap<>();//key父项物料编码  val;分子 分母
        List<String> materialList = new ArrayList<>();//存储物料编号用来查询权重系数
        for (VtuzxMap bom : bomQuery) {
            String materialNo = VtuzxUtil.getString(bom, "FMATERIALID.FNUMBER");//物料编号
            double denominator = VtuzxUtil.getDouble(bom, "FDENOMINATOR");//分母
            double numerator = VtuzxUtil.getDouble(bom, "FNUMERATOR");//分子
            Map<String, Object> data = VtuzxUtil.getObject(bomQueryMap, materialNo);
            //无需判断当前父项物料是否在map中有分子分母的信息，直接添加 有的话就覆盖
            Map<String, Object> numMap = new HashMap<>();
            numMap.put("denominator", denominator);
            numMap.put("numerator", numerator);
            bomQueryMap.put(materialNo, numMap);
            if (!materialList.contains(materialNo)) {
                materialList.add(materialNo);
            }
        }
        //查询物料权重系数
        String materialCond = StringUtils.collectionToDelimitedString(materialList, ",", "'", "'");
        List<VtuzxMap> materialQuery = kingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
                        "F_PSUH_QZXS1",
                        "F_PSUH_QZXS2",
                        "FNumber"
                ),
                String.format("FNumber in (%s)", materialCond), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialQuery)) {
            throw new VtuzxException(String.format("[%s]的权重系数不存在", materialCond));
        }
        Map<String, Object> materialQueryMap = new HashMap<>();//key:物料编码  val:权重系数1 权重系数2
        for (VtuzxMap material : materialQuery) {
            String materialNo = VtuzxUtil.getString(material, "FNumber");//物料编码
            double weight1 = VtuzxUtil.getDouble(material, "F_PSUH_QZXS1");//权重系数1
            double weight2 = VtuzxUtil.getDouble(material, "F_PSUH_QZXS2");//权重系数2
            //无需判断当前物料编码是否在map中有权重系数的信息，直接添加，有的话就覆盖
            Map<String, Object> materialNumMap = new HashMap<>();
            materialNumMap.put("weight1", weight1);
            materialNumMap.put("weight2", weight2);
            materialQueryMap.put(materialNo, materialNumMap);
        }
        //如果当前物料没有bom的话默认分子分母都是1
        for (VtuzxMap kingdeePrdOrder : kingdeeBillNoList) {
            String kingdeeMaterialNo = VtuzxUtil.getString(kingdeePrdOrder, "kingdeeMaterialNo"); //物料编号
            double kingdeeQty = VtuzxUtil.getDouble(kingdeePrdOrder, "fQty");
            Map<String, Object> numMap = VtuzxUtil.getObject(bomQueryMap, kingdeeMaterialNo);
            Map<String, Object> materialNumMap = VtuzxUtil.getObject(materialQueryMap, kingdeeMaterialNo);
            double denominator;
            double numerator;
            double weight1;
            double weight2;
            if (!VtuzxUtil.isEmpty(numMap)) {
                //如果当前物料有分子分母正常计算系数，没有的话默认分子分母是1
                denominator = VtuzxUtil.getDouble(numMap, "denominator");//分母
                numerator = VtuzxUtil.getDouble(numMap, "numerator");//分子
            } else {
                denominator = 1;//分母
                numerator = 1;//分子
            }
            if(!VtuzxUtil.isEmpty(materialNumMap)){
                //如果当前物料有权重系数正常计算系数，没有的话默认权重系数是1
                weight1 = VtuzxUtil.getDouble(materialNumMap, "weight1");//权重系数1
                weight2 = VtuzxUtil.getDouble(materialNumMap, "weight2");//权重系数2
            }else {
                weight1 = 1;//权重系数1
                weight2 = 1;//权重系数2
            }
            double coefficient = kingdeeQty * numerator * weight1 * weight2 / denominator;
            //总的系数
            materialCount += coefficient;
            kingdeePrdOrder.append("coefficient", coefficient);
            double noWeightCoefficient = kingdeeQty * numerator / denominator;
            //总的系数(原领料数)
            noWeightMaterialCount += noWeightCoefficient;
            kingdeePrdOrder.append("noWeightCoefficient", noWeightCoefficient);
        }

        materialCount = BigDecimal.valueOf(materialCount).setScale(2, RoundingMode.HALF_UP).doubleValue();
        noWeightMaterialCount = BigDecimal.valueOf(noWeightMaterialCount).setScale(2, RoundingMode.HALF_UP).doubleValue();
        //循环全部生产订单
        int size = kingdeeBillNoList.size();
        for (VtuzxMap kingdeeBillNoMap : kingdeeBillNoList) {
            String kingdeeBillNo = VtuzxUtil.getString(kingdeeBillNoMap, "kingdeeBillNo");
            double fQty = VtuzxUtil.getDouble(kingdeeBillNoMap, "fQty");
            List<Map<String, Object>> fMaterialBomEntry = new ArrayList<>();
            List<VtuzxMap> materialBomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                            "FID",
                            "FBillNo",
                            "FMOBillNO",
                            "FMaterialID2.FNumber",
                            "FUnitID2.FNumber",
                            "FNeedQty2",
                            "FEntity_FEntryID"
                    ),
                    String.format("FMOBillNO = '%s'", kingdeeBillNo), null, 0, 0);
            if (VtuzxUtil.isEmpty(materialBomQuery)) return;
            String fid = VtuzxUtil.getString(materialBomQuery.get(0), "FID");
            String entryId = VtuzxUtil.getString(materialBomQuery.get(0), "FEntity_FEntryID");
            //留一个原单据的分录
            materialPickInner(materialBomQuery.get(0), fMaterialBomEntry);
            double noWeightQty = 0d;
            boolean last = false;
            size--;
            if (size == 0) {
                last = true;
            }
            //fQty 生产订单数 materialCount 同一billNo生产订单下的数量*（分子/分母）的总和
            for (Document bomPickDoc : bomPickList) {
                double lastNoWeightCount = VtuzxUtil.getDouble(bomPickDoc, "count");
                bomPickDoc.append("lastNoWeightCount", lastNoWeightCount); //剩余数量(原领料数)
                noWeightQty = ppBomInnerSDBn(client, bomPickDoc, kingdeeBillNoMap, fQty, taskBillNo, materialCount, materialMap, fMaterialBomEntry, last, noWeightMaterialCount);
            }
            Map<String, Object> prdPickOrderParam = new LinkedHashMap<>();
            Map<String, Object> prdPickOrderModel = new LinkedHashMap<>();
            prdPickOrderModel.put("FID", fid);
            prdPickOrderModel.put("FEntity", fMaterialBomEntry);
            prdPickOrderParam.put("NeedUpDateFields", new ArrayList<>());
            prdPickOrderParam.put("NeedReturnFields", new ArrayList<>());
            prdPickOrderParam.put("IsDeleteEntry", true);
            prdPickOrderParam.put("SubSystemId", "");
            prdPickOrderParam.put("IsVerifyBaseDataField", true);
            prdPickOrderParam.put("IsEntryBatchFill", false);
            prdPickOrderParam.put("ValidateFlag", true);
            prdPickOrderParam.put("NumberSearch", true);
            prdPickOrderParam.put("InterationFlags", "");
            prdPickOrderParam.put("Model", prdPickOrderModel);
            param.append("PRD_PPBOM", prdPickOrderParam);
            List<VtuzxMap> prdPPBomList = kingdeeService.save(client, "PRD_PPBOM", prdPickOrderParam);
            VtuzxMap stkOutStockMap = prdPPBomList.get(0);
            String number = VtuzxUtil.getString(stkOutStockMap, "Number");
            //查新增后的分录id
            List<VtuzxMap> materialBomTwoQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                            "FID",
                            "FBillNo",
                            "FMOBillNO",
                            "FMaterialID2.FNumber",
                            "FUnitID2.FNumber",
                            "FNeedQty2",
                            "FEntity_FEntryID"
                    ),
                    String.format("FBillNo = '%s'", number), null, 0, 0);
            if (VtuzxUtil.isEmpty(materialBomTwoQuery)) return;
            List<Map<String, Object>> entryIdList = new ArrayList<>();
            for (VtuzxMap materialBomTwo : materialBomTwoQuery) {
                Map<String, Object> map = new LinkedHashMap<>();
                String fEntryID = VtuzxUtil.getString(materialBomTwo, "FEntity_FEntryID");
                if (!fEntryID.equals(entryId)) {
                    map.put("FEntryID", fEntryID);
                    entryIdList.add(map);
                }
            }
            Map<String, Object> prdPickOrderTwoParam = new LinkedHashMap<>();
            Map<String, Object> prdPickOrderTwoModel = new LinkedHashMap<>();
            prdPickOrderTwoModel.put("FID", fid);
            prdPickOrderTwoModel.put("FEntity", entryIdList);
            prdPickOrderTwoParam.put("NeedUpDateFields", new ArrayList<>());
            prdPickOrderTwoParam.put("NeedReturnFields", new ArrayList<>());
            prdPickOrderTwoParam.put("IsDeleteEntry", true);
            prdPickOrderTwoParam.put("SubSystemId", "");
            prdPickOrderTwoParam.put("IsVerifyBaseDataField", true);
            prdPickOrderTwoParam.put("IsEntryBatchFill", false);
            prdPickOrderTwoParam.put("ValidateFlag", true);
            prdPickOrderTwoParam.put("NumberSearch", true);
            prdPickOrderTwoParam.put("InterationFlags", "");
            prdPickOrderTwoParam.put("Model", prdPickOrderTwoModel);
            param.append("PRD_PPBOM", prdPickOrderTwoParam);
            List<VtuzxMap> prdPPBomsList = kingdeeService.save(client, "PRD_PPBOM", prdPickOrderTwoParam);
            VtuzxMap prdPPBomsMap = prdPPBomsList.get(0);
            String bomNumber = VtuzxUtil.getString(prdPPBomsMap, "Number");
            kingdeeService.submit(client, "PRD_PPBOM", "0", bomNumber);
            kingdeeService.audit(client, "PRD_PPBOM", "0", bomNumber, "STK_InvCheckResult");
            //生产订单执行至开工
            kingdeeService.toRelease(client, "PRD_MO", "ToStart", "0", kingdeeBillNo);
            //修改生产订单的下达日期
            try {
                kingdeeService.orderUpdate(client, "PRD_MO", kingdeeBillNo, orderDate);
            } catch (Exception e) {
                _logger.info(e.getMessage());
            }
            //用料清单下推生产领料
            List<String> bomNumberList = new ArrayList<>();
            bomNumberList.add(bomNumber);
            Map<String, Object> bomToPickMap = new LinkedHashMap<>();
            bomToPickMap.put("Ids", "");
            bomToPickMap.put("Numbers", bomNumberList);
            bomToPickMap.put("EntryIds", "");
            bomToPickMap.put("RuleId", VtuzxUtil.getString(prdPushRuleDao.findOne(Criteria
                    .where("ruleName").is("PPBOMPushPickMtrl")
                    .and("ruleType").is("sorting")
                    .and("tokenType").is("kingdee3")
            ), "ruleId"));
            bomToPickMap.put("TargetBillTypeId", "");
            bomToPickMap.put("TargetOrgId", 0);
            bomToPickMap.put("IsEnableDefaultRule", false);
            bomToPickMap.put("IsDraftWhenSaveFail", false);
            bomToPickMap.put("CustomParams", new VtuzxMap());
            param.append("PRD_PPBOM", bomToPickMap);
            List<VtuzxMap> pickBillList = kingdeeService.push(client, "PRD_PPBOM", bomToPickMap);
            VtuzxMap pickBillMap = pickBillList.get(0);
            String kingdeePickBillNo = VtuzxUtil.getString(pickBillMap, "Number");
            String id = VtuzxUtil.getString(pickBillMap, "Id");
            Map<String, Object> updatePickParam = new LinkedHashMap<>();
            Map<String, Object> updatePickModel = new LinkedHashMap<>();
            updatePickModel.put("FID", id);
            if (!"Invalid Date".equals(pickTime)) {
                updatePickModel.put("FDate", pickTime);//分选领料单的单据日期
            } else {
                updatePickModel.put("FDate", createTime);//分选领料单的单据日期
            }
            /*20251015===日期*/
            /*if (!"Invalid Date".equals(pickTime)) {
                updatePickModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));//分选领料单的单据日期(当前时间)
            } else {
                updatePickModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));//分选领料单的单据日期(当前时间)
            }*/
            updatePickModel.put("F_sclld_ZTLLR", createName);
            updatePickModel.put("F_sclld_ZTDJH", billNo);
            updatePickModel.put("F_sclld_SJLY", source);
            updatePickModel.put("F_sclld_ZTLLSJ", createTime);
            updatePickModel.put("F_sclld_YLLS", noWeightQty);
            updatePickParam.put("NeedUpDateFields", new ArrayList<>());
            updatePickParam.put("NeedReturnFields", new ArrayList<>());
            updatePickParam.put("IsDeleteEntry", true);
            updatePickParam.put("SubSystemId", "");
            updatePickParam.put("IsVerifyBaseDataField", true);
            updatePickParam.put("IsEntryBatchFill", false);
            updatePickParam.put("ValidateFlag", true);
            updatePickParam.put("NumberSearch", true);
            updatePickParam.put("InterationFlags", "");
            updatePickParam.put("Model", updatePickModel);
            param.append("PRD_PickMtrl", updatePickParam);
            try {
                kingdeeService.save(client, "PRD_PickMtrl", updatePickParam);
                kingdeeService.submit(client, "PRD_PickMtrl", "0", kingdeePickBillNo);
                kingdeeService.audit(client, "PRD_PickMtrl", "0", kingdeePickBillNo, "STK_InvCheckResult");
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
            historyDoc.append("kingdeeNumber", kingdeePickBillNo);
            historyDoc.append("prdPickOrder", true);
        }
    }

    @Override
    public void syncStockTransferOrder(ObjectId userId, String name, String billNo, String source, String taskTime) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }

        List<Document> prdPickOrderList = new ArrayList<>();
        //领料和补料根据物料和批次先存到一个map集合里，为了计算最终数量
        Map<String, Object> bomMap = new HashMap<>();//k:物料加批次+仓库，v:领料和补料里的值
        String taskBillNo = "";
        Iterator<Document> bomPickDocItr = materialBomPickDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (bomPickDocItr.hasNext()) {
            Document bomPickDoc = bomPickDocItr.next();
            String materialNo = VtuzxUtil.getString(bomPickDoc, "materialNo");
            String batchNo = VtuzxUtil.getString(bomPickDoc, "batchNo");
            String stockNo = VtuzxUtil.getString(bomPickDoc, "stockNo");
            taskBillNo = VtuzxUtil.getString(bomPickDoc, "taskBillNo");
            Document bomDoc = (Document) bomMap.get(materialNo + "_" + batchNo + "_" + stockNo);
            if (VtuzxUtil.isEmpty(bomDoc)) {//当前还没有值的话
                bomPickDoc.append("lastCount", VtuzxUtil.getDouble(bomPickDoc, "count"));
                bomMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomPickDoc);
            } else {//有值的话之前数量加上现在数量
                double lastCount = VtuzxUtil.getDouble(bomDoc, "lastCount");
                bomDoc.replace("lastCount", lastCount + VtuzxUtil.getDouble(bomPickDoc, "count"));
                bomMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomDoc);
            }
        }
        Iterator<Document> bomSupplementItr = materialBomSupplementDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo), null, 0, 0);
        while (bomSupplementItr.hasNext()) {
            Document bomSupplementDoc = bomSupplementItr.next();
            String materialNo = VtuzxUtil.getString(bomSupplementDoc, "materialNo");
            String batchNo = VtuzxUtil.getString(bomSupplementDoc, "batchNo");
            String stockNo = VtuzxUtil.getString(bomSupplementDoc, "stockNo");
            Document bomDoc = (Document) bomMap.get(materialNo + "_" + batchNo + "_" + stockNo);
            if (VtuzxUtil.isEmpty(bomDoc)) {//当前还没有值的话
                bomSupplementDoc.append("lastCount", VtuzxUtil.getDouble(bomSupplementDoc, "count"));
                bomMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomSupplementDoc);
            } else {//有值的话之前数量加上现在数量
                double lastCount = VtuzxUtil.getDouble(bomDoc, "lastCount");
                bomDoc.replace("lastCount", lastCount + VtuzxUtil.getDouble(bomSupplementDoc, "count"));
                bomMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomDoc);
            }
        }
        //循环map集合把value放到list集合中
        for (Map.Entry entry : bomMap.entrySet()) {
            Document bomDoc = (Document) entry.getValue();
            prdPickOrderList.add(bomDoc);
        }
        //查看是否有退料
        Iterator<Document> prdInItr = prdInDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo).and("return").is(true), null, 0, 0);
        List<Document> prdInList = new ArrayList<>();
        while (prdInItr.hasNext()) {
            Document prdInDoc = prdInItr.next();
            prdInList.add(prdInDoc);
        }
        if (!VtuzxUtil.isEmpty(prdInList)) {
            for (Document bomDoc : prdPickOrderList) {
                String materialNo = VtuzxUtil.getString(bomDoc, "materialNo");
                String batchNo = VtuzxUtil.getString(bomDoc, "batchNo");
                String stockNo = VtuzxUtil.getString(bomDoc, "stockNo");
                double lastCount = VtuzxUtil.getDouble(bomDoc, "lastCount");
                for (Document returnDoc : prdInList) {
                    String returnMaterialNo = VtuzxUtil.getString(returnDoc, "materialNo");
                    String returnBatchNo = VtuzxUtil.getString(returnDoc, "batchNo");
                    String returnStockNo = VtuzxUtil.getString(returnDoc, "stockNo");
                    double returnCount = VtuzxUtil.getDouble(returnDoc, "count");
                    //&& stockNo.equals(returnStockNo)
                    if (materialNo.equals(returnMaterialNo) && batchNo.equals(returnBatchNo)) {
                        //判断退料数量是否大于领料数量
                        if (lastCount >= returnCount) {
                            bomDoc.replace("lastCount", lastCount - returnCount);
                            bomDoc.replace("count", lastCount - returnCount);
                            returnDoc.replace("count", 0);
                            lastCount = lastCount - returnCount;
                        } else {
                            bomDoc.replace("lastCount", lastCount);
                            returnDoc.replace("count", returnCount - lastCount);
                        }

                    }
                }
            }
        }

        historyDoc.append("billNo", billNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", prdPickOrderList);
        historyDoc.append("event", "transferOrder");
        historyDoc.append("taskTime", taskTime);
        try {
            syncStockTransferOrderInner(historyDoc);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("transferOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    @Override
    public void syncStockTransferOrderBn(ObjectId userId, String name, String billNo, String source, String taskTime) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }

        List<Document> prdPickOrderList = new ArrayList<>();
        //领料和补料根据物料和批次先存到一个map集合里，为了计算最终数量
        Map<String, Object> bomMap = new HashMap<>();//k:物料加批次+仓库，v:领料和补料里的值
        String taskBillNo = "";
        Iterator<Document> bomPickDocItr = materialBomPickDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (bomPickDocItr.hasNext()) {
            Document bomPickDoc = bomPickDocItr.next();
            String materialNo = VtuzxUtil.getString(bomPickDoc, "materialNo");
            String batchNo = VtuzxUtil.getString(bomPickDoc, "batchNo");
            taskBillNo = VtuzxUtil.getString(bomPickDoc, "taskBillNo");
            if (batchNo != null && batchNo.toUpperCase().startsWith("BN")) {
                String stockNo = VtuzxUtil.getString(bomPickDoc, "stockNo");
                Document bomDoc = (Document) bomMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                if (VtuzxUtil.isEmpty(bomDoc)) {//当前还没有值的话
                    bomPickDoc.append("lastCount", VtuzxUtil.getDouble(bomPickDoc, "count"));
                    bomMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomPickDoc);
                } else {//有值的话之前数量加上现在数量
                    double lastCount = VtuzxUtil.getDouble(bomDoc, "lastCount");
                    bomDoc.replace("lastCount", lastCount + VtuzxUtil.getDouble(bomPickDoc, "count"));
                    bomMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomDoc);
                }
            }
        }
        Iterator<Document> bomSupplementItr = materialBomSupplementDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo), null, 0, 0);
        while (bomSupplementItr.hasNext()) {
            Document bomSupplementDoc = bomSupplementItr.next();
            String materialNo = VtuzxUtil.getString(bomSupplementDoc, "materialNo");
            String batchNo = VtuzxUtil.getString(bomSupplementDoc, "batchNo");
            if (batchNo != null && batchNo.toUpperCase().startsWith("BN")) {
                String stockNo = VtuzxUtil.getString(bomSupplementDoc, "stockNo");
                Document bomDoc = (Document) bomMap.get(materialNo + "_" + batchNo + "_" + stockNo);
                if (VtuzxUtil.isEmpty(bomDoc)) {//当前还没有值的话
                    bomSupplementDoc.append("lastCount", VtuzxUtil.getDouble(bomSupplementDoc, "count"));
                    bomMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomSupplementDoc);
                } else {//有值的话之前数量加上现在数量
                    double lastCount = VtuzxUtil.getDouble(bomDoc, "lastCount");
                    bomDoc.replace("lastCount", lastCount + VtuzxUtil.getDouble(bomSupplementDoc, "count"));
                    bomMap.put(materialNo + "_" + batchNo + "_" + stockNo, bomDoc);
                }
            }
        }
        //循环map集合把value放到list集合中
        for (Map.Entry entry : bomMap.entrySet()) {
            Document bomDoc = (Document) entry.getValue();
            prdPickOrderList.add(bomDoc);
        }
        //查看是否有退料
        Iterator<Document> prdInItr = prdInDetailDao.findList(Criteria.where("taskBillNo").is(taskBillNo).and("return").is(true), null, 0, 0);
        List<Document> prdInList = new ArrayList<>();
        while (prdInItr.hasNext()) {
            Document prdInDoc = prdInItr.next();
            prdInList.add(prdInDoc);
        }
        if (!VtuzxUtil.isEmpty(prdInList)) {
            for (Document bomDoc : prdPickOrderList) {
                String materialNo = VtuzxUtil.getString(bomDoc, "materialNo");
                String batchNo = VtuzxUtil.getString(bomDoc, "batchNo");
                String stockNo = VtuzxUtil.getString(bomDoc, "stockNo");
                double lastCount = VtuzxUtil.getDouble(bomDoc, "lastCount");
                for (Document returnDoc : prdInList) {
                    String returnMaterialNo = VtuzxUtil.getString(returnDoc, "materialNo");
                    String returnBatchNo = VtuzxUtil.getString(returnDoc, "batchNo");
                    String returnStockNo = VtuzxUtil.getString(returnDoc, "stockNo");
                    double returnCount = VtuzxUtil.getDouble(returnDoc, "count");
                    //&& stockNo.equals(returnStockNo)
                    if (materialNo.equals(returnMaterialNo) && batchNo.equals(returnBatchNo)) {
                        //判断退料数量是否大于领料数量
                        if (lastCount >= returnCount) {
                            bomDoc.replace("lastCount", lastCount - returnCount);
                            bomDoc.replace("count", lastCount - returnCount);
                            lastCount = lastCount - returnCount;
                        } else {
                            bomDoc.replace("lastCount", lastCount);
                            returnDoc.replace("count", returnCount - lastCount);
                        }

                    }
                }
            }
        }

        historyDoc.append("billNo", billNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", prdPickOrderList);
        historyDoc.append("event", "transferOrder");
        historyDoc.append("taskTime", taskTime);
        try {
            syncStockTransferOrderInnerBn(historyDoc);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("transferOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    private void syncStockTransferOrderInner(Document historyDoc) throws Exception {
        List<Document> prdPickOrder = VtuzxUtil.getObject(historyDoc, "data");
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");
        Document materialBomPick = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
        String createUserName = VtuzxUtil.getString(materialBomPick, "createUserName");
        String auditUserName = VtuzxUtil.getString(materialBomPick, "auditUserName");
        String pickCreateTime = "";
        //判断订单日期是否上传
        String taskTime = VtuzxUtil.getString(historyDoc, "taskTime");
        if ("Invalid Date".equals(taskTime) || VtuzxUtil.isEmpty(taskTime)) {
            pickCreateTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPick, "createTime"));
        } else {
            pickCreateTime = taskTime;
        }

        syncStockTransferOrderCenter(prdPickOrder, historyDoc, source, createUserName, auditUserName, pickCreateTime, billNo, true);

    }

    private void syncStockTransferOrderInnerBn(Document historyDoc) throws Exception {
        List<Document> prdPickOrder = VtuzxUtil.getObject(historyDoc, "data");
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");
        Document materialBomPick = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
        String createUserName = VtuzxUtil.getString(materialBomPick, "createUserName");
        String auditUserName = VtuzxUtil.getString(materialBomPick, "auditUserName");
        String pickCreateTime = "";
        //判断订单日期是否上传
        String taskTime = VtuzxUtil.getString(historyDoc, "taskTime");
        if ("Invalid Date".equals(taskTime) || VtuzxUtil.isEmpty(taskTime)) {
            pickCreateTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(materialBomPick, "createTime"));
        } else {
            pickCreateTime = taskTime;
        }
        syncStockTransferOrderCenterBn(prdPickOrder, historyDoc, source, createUserName, auditUserName, pickCreateTime, billNo, true);
    }


    @Override
    public void syncStockTransferOrderMain(ObjectId userId, String name, String billNo, String source) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        boolean success = VtuzxUtil.getBoolean(historyDoc, "success");
//        if (success) {
//            return;
//        }
        List<Document> prdPickOrderList = new ArrayList<>();
        Document allocationDoc = allocationDao.findOne(Criteria.where("billNo").is(billNo));
        int boxCount = VtuzxUtil.getInt(allocationDoc, "boxCount");
        if (boxCount == 0) {
            historyDoc.append("transferOrder", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }
        historyDoc.append("billNo", billNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", allocationDoc);
        historyDoc.append("event", "transferOrder");
        try {
            syncStockTransferOrderMainInner(historyDoc);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("transferOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    private void syncStockTransferOrderMainInner(Document historyDoc) throws Exception {
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");
        Document data = VtuzxUtil.getObject(historyDoc, "data");
        String createUserName = VtuzxUtil.getString(data, "createUserName");
        String auditUserName = VtuzxUtil.getString(data, "auditUserName");
        String createTime = VtuzxUtil.formatYmdF(VtuzxUtil.getObject(data, "createTime"));
        List<Document> allList = new ArrayList<>();
        Iterator<Document> allItr = allocationDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (allItr.hasNext()) {
            Document allDoc = allItr.next();
            allList.add(allDoc);
        }

        syncStockTransferOrderCenterPDA(allList, historyDoc, source, createUserName, auditUserName, createTime, billNo, false);
    }

    private void syncStockTransferOrderCenter(List<Document> prdPickOrder, Document historyDoc, String source, String createUserName, String auditUserName, String pickCreateTime, String billNo, boolean sorting) throws Exception {
        if (prdPickOrder.size() == 0) {
            throw new VtuzxException("不存在分录,请确认订单是否正确!");
        }
        Map<String, Object> stockTransferModel = new LinkedHashMap<>();
        Map<String, Object> stockTransferParam = new LinkedHashMap<>();
        List<Map<String, Object>> stockTransferEntryList = new ArrayList<>();

        List<String> materialNoList = new ArrayList<>();
        for (Document prdPick : prdPickOrder) {
            String materialNo = VtuzxUtil.getString(prdPick, "materialNo");
            materialNoList.add(materialNo);
        }

        VtuzxMap materialCenterMap = new VtuzxMap();
        Iterator<Document> materialItr = materialDao.findList(Criteria.where("fNumber").in(materialNoList), null, 0, 0);
        while (materialItr.hasNext()) {
            Document materialDoc = materialItr.next();
            String materialNo = VtuzxUtil.getString(materialDoc, "fNumber");
            String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
            materialCenterMap.append(materialNo, unit);
        }

        for (Document prdPick : prdPickOrder) {
            String materialNo = VtuzxUtil.getString(prdPick, "materialNo");
            String unit = VtuzxUtil.getString(materialCenterMap, materialNo);
            if (VtuzxUtil.isEmpty(unit)) {
                throw new VtuzxException(String.format("物料[%s]不存在", materialNo));
            }
            String batchNo = VtuzxUtil.getString(prdPick, "batchNo");
            String stockNo = VtuzxUtil.getString(prdPick, "stockNo");
            String toStockNo = VtuzxUtil.getString(prdPick, "toStockNo");
            String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdPick, "createTime"));
            double count = VtuzxUtil.getDouble(prdPick, "lastCount");

            if (!stockNo.equals(toStockNo)) {//防止明细中也会有同仓库调拨
                Map<String, Object> stockTransferEntry = new LinkedHashMap<>();
                stockTransferEntry.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
                stockTransferEntry.put("FUnitID", new VtuzxMap("FNumber", unit));
                stockTransferEntry.put("FQty", count);
                stockTransferEntry.put("FLot", new VtuzxMap("FNumber", batchNo));
                stockTransferEntry.put("FSrcStockId", new VtuzxMap("FNumber", stockNo));
                if (sorting) {
                    stockTransferEntry.put("FDestStockId", new VtuzxMap("FNumber", "0028"));
                } else {
                    stockTransferEntry.put("FDestStockId", new VtuzxMap("FNumber", toStockNo));
                }
                stockTransferEntry.put("FSrcStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                stockTransferEntry.put("FDestStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                stockTransferEntry.put("FBusinessDate", createTime);
                stockTransferEntry.put("FOwnerTypeOutId", "BD_OwnerOrg");
                stockTransferEntry.put("FOwnerOutId", new VtuzxMap("FNumber", "100"));
                stockTransferEntry.put("FOwnerTypeId", "BD_OwnerOrg");
                stockTransferEntry.put("FOwnerId", new VtuzxMap("FNumber", "100"));
                stockTransferEntry.put("FBaseUnitId", new VtuzxMap("FNumber", unit));
                stockTransferEntry.put("FBaseQty", count);
                stockTransferEntry.put("FISFREE", false);
                stockTransferEntry.put("FKeeperTypeId", "BD_KeeperOrg");
                stockTransferEntry.put("FKeeperId", new VtuzxMap("FNumber", "100"));
                stockTransferEntry.put("FKeeperTypeOutId", "BD_KeeperOrg");
                stockTransferEntry.put("FKeeperOutId", new VtuzxMap("FNumber", "100"));
                stockTransferEntry.put("FDestLot", new VtuzxMap("FNumber", batchNo));
                stockTransferEntry.put("FDestMaterialId", new VtuzxMap("FNumber", materialNo));
                stockTransferEntry.put("FSaleUnitId", new VtuzxMap("FNumber", unit));
                stockTransferEntry.put("FSaleQty", count);
                stockTransferEntry.put("FSalBaseQty", count);
                stockTransferEntry.put("FPriceUnitID", new VtuzxMap("FNumber", unit));
                stockTransferEntry.put("FPriceQty", count);
                stockTransferEntry.put("FPriceBaseQty", count);
                stockTransferEntry.put("FTransReserveLink", false);
                stockTransferEntry.put("FCheckDelivery", false);
                stockTransferEntryList.add(stockTransferEntry);
            }

        }

        stockTransferModel.put("FBillTypeID", new VtuzxMap("FNumber", "ZJDB01_SYS"));
        stockTransferModel.put("FBizType", "NORMAL");
        stockTransferModel.put("FTransferDirect", "GENERAL");
        stockTransferModel.put("FTransferBizType", "InnerOrgTransfer");
        stockTransferModel.put("FSettleOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FSaleOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FStockOutOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FOwnerTypeOutIdHead", "BD_OwnerOrg");
        stockTransferModel.put("FOwnerOutIdHead", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FStockOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FIsIncludedTax", true);
        stockTransferModel.put("FIsPriceExcludeTax", true);
        stockTransferModel.put("FExchangeTypeId", new VtuzxMap("FNumber", "HLTX01_SYS"));
        stockTransferModel.put("FOwnerTypeIdHead", "BD_OwnerOrg");
        stockTransferModel.put("FSETTLECURRID", new VtuzxMap("FNumber", "PRE001"));
        stockTransferModel.put("FExchangeRate", 1.0);
        stockTransferModel.put("FOwnerIdHead", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FDate", pickCreateTime);
        stockTransferModel.put("FBaseCurrId", new VtuzxMap("FNumber", "PRE001"));
        Document materialPickDoc = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
        String taskBillNo = "";
        if (!VtuzxUtil.isEmpty(materialPickDoc)) {
            taskBillNo = VtuzxUtil.getString(materialPickDoc, "taskBillNo");
        }
        if (VtuzxUtil.isEmpty(taskBillNo)) {
            taskBillNo = billNo;
        }
        stockTransferModel.put("F_zjdbd_ZTDJH", taskBillNo);//对应任务单号
        stockTransferModel.put("F_zjdbd_CZRY", createUserName);
        stockTransferModel.put("F_zjdbd_FHR", auditUserName);
        stockTransferModel.put("F_zjdbd_SJLY", source);
        stockTransferModel.put("F_zjdbd_ZTYWRQ", pickCreateTime);
        stockTransferModel.put("FBillEntry", stockTransferEntryList);

        stockTransferParam.put("Model", stockTransferModel);
        historyDoc.append("param", new VtuzxMap("STK_TransferDirect", stockTransferParam));
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        //跟生产任务有关的调拨单补审核
        List<VtuzxMap> transferList = kingdeeService.save(client, "STK_TransferDirect", stockTransferParam);
        VtuzxMap transferMap = transferList.get(0);
        String number = VtuzxUtil.getString(transferMap, "Number");
        kingdeeService.submit(client, "STK_TransferDirect", "0", number);
        kingdeeService.audit(client, "STK_TransferDirect", "0", number, "STK_InvCheckResult");
        historyDoc.append("kingdeeNumber", number);
        historyDoc.append("transferOrder", true);
    }

    private void syncStockTransferOrderCenterBn(List<Document> prdPickOrder, Document historyDoc, String source, String createUserName, String auditUserName, String pickCreateTime, String billNo, boolean sorting) throws Exception {
        if (prdPickOrder.size() == 0) {
            throw new VtuzxException("不存在分录,请确认订单是否正确!");
        }
        Map<String, Object> stockTransferModel = new LinkedHashMap<>();
        Map<String, Object> stockTransferParam = new LinkedHashMap<>();
        List<Map<String, Object>> stockTransferEntryList = new ArrayList<>();
        List<String> materialNoList = new ArrayList<>();
        for (Document prdPick : prdPickOrder) {
            String materialNo = VtuzxUtil.getString(prdPick, "materialNo");
            materialNoList.add(materialNo);
        }
        VtuzxMap materialCenterMap = new VtuzxMap();
        Iterator<Document> materialItr = materialDao.findList(Criteria.where("fNumber").in(materialNoList), null, 0, 0);
        while (materialItr.hasNext()) {
            Document materialDoc = materialItr.next();
            String materialNo = VtuzxUtil.getString(materialDoc, "fNumber");
            String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
            materialCenterMap.append(materialNo, unit);
        }
        for (Document prdPick : prdPickOrder) {
            String materialNo = VtuzxUtil.getString(prdPick, "materialNo");
            String unit = VtuzxUtil.getString(materialCenterMap, materialNo);
            if (VtuzxUtil.isEmpty(unit)) {
                throw new VtuzxException(String.format("物料[%s]不存在", materialNo));
            }
            String batchNo = VtuzxUtil.getString(prdPick, "batchNo");
            String stockNo = VtuzxUtil.getString(prdPick, "stockNo");
            String toStockNo = VtuzxUtil.getString(prdPick, "toStockNo");
            String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdPick, "createTime"));
            double count = VtuzxUtil.getDouble(prdPick, "lastCount");
            if (!stockNo.equals(toStockNo)) {//防止明细中也会有同仓库调拨
                Map<String, Object> stockTransferEntry = new LinkedHashMap<>();
                stockTransferEntry.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
                stockTransferEntry.put("FUnitID", new VtuzxMap("FNumber", unit));
                stockTransferEntry.put("FQty", count);
                stockTransferEntry.put("FLot", new VtuzxMap("FNumber", batchNo));
                /*stockTransferEntry.put("FSrcStockId", new VtuzxMap("FNumber", stockNo));*/
                stockTransferEntry.put("FSrcStockId", new VtuzxMap("FNumber", "002"));
                if (sorting) {
                    /*stockTransferEntry.put("FDestStockId", new VtuzxMap("FNumber", "0028"));*/
                    stockTransferEntry.put("FDestStockId", new VtuzxMap("FNumber", "003"));
                } else {
                    stockTransferEntry.put("FDestStockId", new VtuzxMap("FNumber", toStockNo));
                }
                stockTransferEntry.put("FSrcStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                stockTransferEntry.put("FDestStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                stockTransferEntry.put("FBusinessDate", createTime);
                stockTransferEntry.put("FOwnerTypeOutId", "BD_OwnerOrg");
                /*stockTransferEntry.put("FOwnerOutId", new VtuzxMap("FNumber", "100"));*/
                stockTransferEntry.put("FOwnerOutId", new VtuzxMap("FNumber", "200"));
                stockTransferEntry.put("FOwnerTypeId", "BD_OwnerOrg");
                /*stockTransferEntry.put("FOwnerId", new VtuzxMap("FNumber", "100"));*/
                stockTransferEntry.put("FOwnerId", new VtuzxMap("FNumber", "200"));
                stockTransferEntry.put("FBaseUnitId", new VtuzxMap("FNumber", unit));
                stockTransferEntry.put("FBaseQty", count);
                stockTransferEntry.put("FISFREE", false);
                stockTransferEntry.put("FKeeperTypeId", "BD_KeeperOrg");
                /*stockTransferEntry.put("FKeeperId", new VtuzxMap("FNumber", "100"));*/
                stockTransferEntry.put("FKeeperId", new VtuzxMap("FNumber", "200"));
                stockTransferEntry.put("FKeeperTypeOutId", "BD_KeeperOrg");
                /*stockTransferEntry.put("FKeeperOutId", new VtuzxMap("FNumber", "100"));*/
                stockTransferEntry.put("FKeeperOutId", new VtuzxMap("FNumber", "200"));
                stockTransferEntry.put("FDestLot", new VtuzxMap("FNumber", batchNo));
                stockTransferEntry.put("FDestMaterialId", new VtuzxMap("FNumber", materialNo));
                stockTransferEntry.put("FSaleUnitId", new VtuzxMap("FNumber", unit));
                stockTransferEntry.put("FSaleQty", count);
                stockTransferEntry.put("FSalBaseQty", count);
                stockTransferEntry.put("FPriceUnitID", new VtuzxMap("FNumber", unit));
                stockTransferEntry.put("FPriceQty", count);
                stockTransferEntry.put("FPriceBaseQty", count);
                stockTransferEntry.put("FTransReserveLink", false);
                stockTransferEntry.put("FCheckDelivery", false);
                stockTransferEntryList.add(stockTransferEntry);
            }
        }
        stockTransferModel.put("FBillTypeID", new VtuzxMap("FNumber", "ZJDB01_SYS"));
        stockTransferModel.put("FBizType", "NORMAL");
        stockTransferModel.put("FTransferDirect", "GENERAL");
        stockTransferModel.put("FTransferBizType", "InnerOrgTransfer");
/*        stockTransferModel.put("FSettleOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FSaleOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FStockOutOrgId", new VtuzxMap("FNumber", "100"));*/
        stockTransferModel.put("FSettleOrgId", new VtuzxMap("FNumber", "200"));
        stockTransferModel.put("FSaleOrgId", new VtuzxMap("FNumber", "200"));
        stockTransferModel.put("FStockOutOrgId", new VtuzxMap("FNumber", "200"));
        stockTransferModel.put("FOwnerTypeOutIdHead", "BD_OwnerOrg");
/*        stockTransferModel.put("FOwnerOutIdHead", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FStockOrgId", new VtuzxMap("FNumber", "100"));*/
        stockTransferModel.put("FOwnerOutIdHead", new VtuzxMap("FNumber", "200"));
        stockTransferModel.put("FStockOrgId", new VtuzxMap("FNumber", "200"));
        stockTransferModel.put("FIsIncludedTax", true);
        stockTransferModel.put("FIsPriceExcludeTax", true);
        stockTransferModel.put("FExchangeTypeId", new VtuzxMap("FNumber", "HLTX01_SYS"));
        stockTransferModel.put("FOwnerTypeIdHead", "BD_OwnerOrg");
        stockTransferModel.put("FSETTLECURRID", new VtuzxMap("FNumber", "PRE001"));
        stockTransferModel.put("FExchangeRate", 1.0);
        /*stockTransferModel.put("FOwnerIdHead", new VtuzxMap("FNumber", "100"));*/
        stockTransferModel.put("FOwnerIdHead", new VtuzxMap("FNumber", "200"));
        stockTransferModel.put("FDate", pickCreateTime);
        /*20251015===日期*/
        /*stockTransferModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));*/
        stockTransferModel.put("FBaseCurrId", new VtuzxMap("FNumber", "PRE001"));
        Document materialPickDoc = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
        String taskBillNo = "";
        if (!VtuzxUtil.isEmpty(materialPickDoc)) {
            taskBillNo = VtuzxUtil.getString(materialPickDoc, "taskBillNo");
        }
        if (VtuzxUtil.isEmpty(taskBillNo)) {
            taskBillNo = billNo;
        }
        stockTransferModel.put("F_zjdbd_ZTDJH", taskBillNo);//对应任务单号
        stockTransferModel.put("F_zjdbd_CZRY", createUserName);
        stockTransferModel.put("F_zjdbd_FHR", auditUserName);
        stockTransferModel.put("F_zjdbd_SJLY", source);
        stockTransferModel.put("F_zjdbd_ZTYWRQ", pickCreateTime);
        stockTransferModel.put("FBillEntry", stockTransferEntryList);
        stockTransferParam.put("Model", stockTransferModel);
        historyDoc.append("param", new VtuzxMap("STK_TransferDirect", stockTransferParam));
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdeeYX();
        //跟生产任务有关的调拨单补审核
        List<VtuzxMap> transferList = kingdeeService.save(client, "STK_TransferDirect", stockTransferParam);
        VtuzxMap transferMap = transferList.get(0);
        String number = VtuzxUtil.getString(transferMap, "Number");
        kingdeeService.submit(client, "STK_TransferDirect", "0", number);
        kingdeeService.audit(client, "STK_TransferDirect", "0", number, "STK_InvCheckResult");
        historyDoc.append("kingdeeNumber", number);
        historyDoc.append("transferOrder", true);
    }

    //pda调拨
    private void syncStockTransferOrderCenterPDA(List<Document> prdPickOrder, Document historyDoc, String source, String createUserName, String auditUserName, String pickCreateTime, String billNo, boolean sorting) throws Exception {
        if (prdPickOrder.size() == 0) {
            throw new VtuzxException("不存在分录,请确认订单是否正确!");
        }
        Map<String, Object> stockTransferModel = new LinkedHashMap<>();
        Map<String, Object> stockTransferParam = new LinkedHashMap<>();
        List<Map<String, Object>> stockTransferEntryList = new ArrayList<>();

        List<String> materialNoList = new ArrayList<>();
        for (Document prdPick : prdPickOrder) {
            String materialNo = VtuzxUtil.getString(prdPick, "materialNo");
            materialNoList.add(materialNo);
        }

        VtuzxMap materialCenterMap = new VtuzxMap();
        Iterator<Document> materialItr = materialDao.findList(Criteria.where("fNumber").in(materialNoList), null, 0, 0);
        while (materialItr.hasNext()) {
            Document materialDoc = materialItr.next();
            String materialNo = VtuzxUtil.getString(materialDoc, "fNumber");
            String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
            materialCenterMap.append(materialNo, unit);
        }
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
        List<VtuzxMap> materialQuery = kingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
                        "FIsBatchManage",
                        "FNumber"
                ),
                String.format("FNumber  in (%s)", materialNoCond), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialQuery)) return;
        Map<String, Object> materialMap = new HashMap<>();//key:物料编码 val:是否启用批次
        for (VtuzxMap map : materialQuery) {
            String materialNo = VtuzxUtil.getString(map, "FNumber");
            boolean isBatch = VtuzxUtil.getBoolean(map, "FIsBatchManage");
            materialMap.put(materialNo, isBatch);
        }
        for (Document prdPick : prdPickOrder) {
            String materialNo = VtuzxUtil.getString(prdPick, "materialNo");
            String unit = VtuzxUtil.getString(materialCenterMap, materialNo);
            if (VtuzxUtil.isEmpty(unit)) {
                throw new VtuzxException(String.format("物料[%s]不存在", materialNo));
            }
            String batchNo = VtuzxUtil.getString(prdPick, "batchNo");
            String stockNo = VtuzxUtil.getString(prdPick, "stockNo");
            String toStockNo = VtuzxUtil.getString(prdPick, "toStockNo");
            String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdPick, "createTime"));
            double count = VtuzxUtil.getDouble(prdPick, "count");

            if (!stockNo.equals(toStockNo)) {//防止明细中也会有同仓库调拨
                Map<String, Object> stockTransferEntry = new LinkedHashMap<>();
                stockTransferEntry.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
                stockTransferEntry.put("FUnitID", new VtuzxMap("FNumber", unit));
                stockTransferEntry.put("FQty", count);
                boolean isBatch = (Boolean) materialMap.get(materialNo);
                if (isBatch) {
                    stockTransferEntry.put("FLot", new VtuzxMap("FNumber", batchNo));
                }
                stockTransferEntry.put("FSrcStockId", new VtuzxMap("FNumber", stockNo));
                if (sorting) {
                    stockTransferEntry.put("FDestStockId", new VtuzxMap("FNumber", "0028"));
                } else {
                    stockTransferEntry.put("FDestStockId", new VtuzxMap("FNumber", toStockNo));
                }
                stockTransferEntry.put("FSrcStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                stockTransferEntry.put("FDestStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                stockTransferEntry.put("FBusinessDate", createTime);
                stockTransferEntry.put("FOwnerTypeOutId", "BD_OwnerOrg");
                stockTransferEntry.put("FOwnerOutId", new VtuzxMap("FNumber", "100"));
                stockTransferEntry.put("FOwnerTypeId", "BD_OwnerOrg");
                stockTransferEntry.put("FOwnerId", new VtuzxMap("FNumber", "100"));
                stockTransferEntry.put("FBaseUnitId", new VtuzxMap("FNumber", unit));
                stockTransferEntry.put("FBaseQty", count);
                stockTransferEntry.put("FISFREE", false);
                stockTransferEntry.put("FKeeperTypeId", "BD_KeeperOrg");
                stockTransferEntry.put("FKeeperId", new VtuzxMap("FNumber", "100"));
                stockTransferEntry.put("FKeeperTypeOutId", "BD_KeeperOrg");
                stockTransferEntry.put("FKeeperOutId", new VtuzxMap("FNumber", "100"));

                if (isBatch) {
                    stockTransferEntry.put("FDestLot", new VtuzxMap("FNumber", batchNo));
                }
                stockTransferEntry.put("FDestMaterialId", new VtuzxMap("FNumber", materialNo));
                stockTransferEntry.put("FSaleUnitId", new VtuzxMap("FNumber", unit));
                stockTransferEntry.put("FSaleQty", count);
                stockTransferEntry.put("FSalBaseQty", count);
                stockTransferEntry.put("FPriceUnitID", new VtuzxMap("FNumber", unit));
                stockTransferEntry.put("FPriceQty", count);
                stockTransferEntry.put("FPriceBaseQty", count);
                stockTransferEntry.put("FTransReserveLink", false);
                stockTransferEntry.put("FCheckDelivery", false);
                stockTransferEntryList.add(stockTransferEntry);
            }

        }

        stockTransferModel.put("FBillTypeID", new VtuzxMap("FNumber", "ZJDB01_SYS"));
        stockTransferModel.put("FBizType", "NORMAL");
        stockTransferModel.put("FTransferDirect", "GENERAL");
        stockTransferModel.put("FTransferBizType", "InnerOrgTransfer");
        stockTransferModel.put("FSettleOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FSaleOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FStockOutOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FOwnerTypeOutIdHead", "BD_OwnerOrg");
        stockTransferModel.put("FOwnerOutIdHead", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FStockOrgId", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FIsIncludedTax", true);
        stockTransferModel.put("FIsPriceExcludeTax", true);
        stockTransferModel.put("FExchangeTypeId", new VtuzxMap("FNumber", "HLTX01_SYS"));
        stockTransferModel.put("FOwnerTypeIdHead", "BD_OwnerOrg");
        stockTransferModel.put("FSETTLECURRID", new VtuzxMap("FNumber", "PRE001"));
        stockTransferModel.put("FExchangeRate", 1.0);
        stockTransferModel.put("FOwnerIdHead", new VtuzxMap("FNumber", "100"));
        stockTransferModel.put("FDate", pickCreateTime);
        stockTransferModel.put("FBaseCurrId", new VtuzxMap("FNumber", "PRE001"));
        Document materialPickDoc = materialBomPickDao.findOne(Criteria.where("billNo").is(billNo));
        String taskBillNo = "";
        if (!VtuzxUtil.isEmpty(materialPickDoc)) {
            taskBillNo = VtuzxUtil.getString(materialPickDoc, "taskBillNo");
        }
        if (VtuzxUtil.isEmpty(taskBillNo)) {
            taskBillNo = billNo;
        }
        stockTransferModel.put("F_zjdbd_ZTDJH", taskBillNo);//对应任务单号
        stockTransferModel.put("F_zjdbd_CZRY", createUserName);
        stockTransferModel.put("F_zjdbd_FHR", auditUserName);
        stockTransferModel.put("F_zjdbd_SJLY", source);
        stockTransferModel.put("F_zjdbd_ZTYWRQ", pickCreateTime);
        stockTransferModel.put("FBillEntry", stockTransferEntryList);

        stockTransferParam.put("Model", stockTransferModel);
        historyDoc.append("param", new VtuzxMap("STK_TransferDirect", stockTransferParam));

        List<VtuzxMap> transferList = kingdeeService.save(client, "STK_TransferDirect", stockTransferParam);
        VtuzxMap transferMap = transferList.get(0);
        String number = VtuzxUtil.getString(transferMap, "Number");
        kingdeeService.submit(client, "STK_TransferDirect", "0", number);
        kingdeeService.audit(client, "STK_TransferDirect", "0", number, "STK_InvCheckResult");
        historyDoc.append("kingdeeNumber", number);
        historyDoc.append("transferOrder", true);
    }

    @Override
    public void syncPrdInStockOrderSorting(ObjectId userId, String name, String billNo, String source, String prdInTime) throws Exception {

        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        boolean success = VtuzxUtil.getBoolean(historyDoc, "success");
//        if (success) {
//            return;
//        }
        Document prdInDoc = prdInDao.findOne(Criteria.where("billNo").is(billNo));
        int boxCount = VtuzxUtil.getInt(prdInDoc, "boxCount");
        if (boxCount == 0) {
            historyDoc.append("prdInStockStock", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }
        historyDoc.append("billNo", billNo);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("source", source);
        historyDoc.append("data", prdInDoc);
        historyDoc.append("event", "prdInStock");
        historyDoc.append("prdInTime", prdInTime);
        try {
            syncPrdInStockOrderSortingInner(historyDoc);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdInStockStock", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    @Override
    public void syncPrdInStockOrderSortingBn(ObjectId userId, String name, String billNo, String source, String prdInTime) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        boolean success = VtuzxUtil.getBoolean(historyDoc, "success");
//        if (success) {
//            return;
//        }
        Document prdInDoc = prdInDao.findOne(Criteria.where("billNo").is(billNo));
        Iterator<Document> inStockDetailItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        List<Document> validDetails = new ArrayList<>();
        while (inStockDetailItr.hasNext()) {
            Document detail = inStockDetailItr.next();
            String batchNo = VtuzxUtil.getString(detail, "batchNo");
            if (batchNo != null && batchNo.toUpperCase().startsWith("BN")) {
                validDetails.add(detail);
            }
        }
        if (validDetails.isEmpty()) {
            historyDoc.append("prdInStockStock", false).append("message", "无BN批次物料").append("success", true);
            return;
        }
        /*int boxCount = VtuzxUtil.getInt(prdInDoc, "boxCount");*/
        int validBoxCount = validDetails.size();
        if (validBoxCount == 0) {
            historyDoc.append("prdInStockStock", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                historyDoc.append("filteredDetails", validDetails);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }
        historyDoc.append("billNo", billNo);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("source", source);
        historyDoc.append("data", prdInDoc);
        historyDoc.append("event", "prdInStock");
        historyDoc.append("prdInTime", prdInTime);
        historyDoc.append("filteredDetails", validDetails);
        try {
            syncPrdInStockOrderSortingInnerBn(historyDoc);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdInStockStock", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    //分选入库
    private void syncPrdInStockOrderSortingInner(Document historyDoc) throws Exception {
        Document prdIn = VtuzxUtil.getObject(historyDoc, "data");
        String orderPrdInTime = VtuzxUtil.getString(historyDoc, "prdInTime");//手动选择的入库日期

        String createUserName = VtuzxUtil.getString(prdIn, "createUserName");
        //String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdIn, "createTime"));
        String taskBillNo = VtuzxUtil.getString(prdIn, "taskBillNo");
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");

        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                        "FBillNo"
                ),
                String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 0);

        if (VtuzxUtil.isEmpty(prdOrderQuery)) return;

        List<String> prdBillNoList = new ArrayList<>();
        for (VtuzxMap prdOrderMap : prdOrderQuery) {
            String kingdeeBillNo = VtuzxUtil.getString(prdOrderMap, "FBillNo");
            prdBillNoList.add(kingdeeBillNo);
        }

        //用生产订单下推生产入库
        Map<String, Object> prdToInStockMap = new LinkedHashMap<>();
        prdToInStockMap.put("Ids", "");
        prdToInStockMap.put("Numbers", prdBillNoList);
        prdToInStockMap.put("EntryIds", "");
        prdToInStockMap.put("RuleId", "ora_rule");
        prdToInStockMap.put("TargetBillTypeId", "");
        prdToInStockMap.put("TargetOrgId", 0);
        prdToInStockMap.put("IsEnableDefaultRule", false);
        prdToInStockMap.put("IsDraftWhenSaveFail", false);
        prdToInStockMap.put("CustomParams", new VtuzxMap());
        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        param.append("PRD_MO", prdToInStockMap);
        List<VtuzxMap> prdToInStockList = kingdeeService.push(client, "PRD_MO", prdToInStockMap);
//        VtuzxMap prdToInStocks = prdToInStockList.get(0);
        for (VtuzxMap prdToInStocks : prdToInStockList) {
            String prdToInStockBillNo = VtuzxUtil.getString(prdToInStocks, "Number");
            String prdToInStockId = VtuzxUtil.getString(prdToInStocks, "Id");
            //修改生产入库
            List<VtuzxMap> inStockQuery = kingdeeService.query(client, "PRD_INSTOCK", new VtuzxArrayList<>(
                            "FBillNo",
                            "FEntity_FEntryID",
                            "FMaterialId.FNumber",
                            "FLot.FNumber",//批次号
                            "FMustQty"
                    ),
                    String.format("FBillNo = '%s'", prdToInStockBillNo), null, 0, 1);
            if (VtuzxUtil.isEmpty(inStockQuery)) return;

            List<Map<String, Object>> prdInStockList = new ArrayList<>();//金蝶
            Map<String, Object> prdInStockParam = new LinkedHashMap<>();
            Map<String, Object> prdInStockModel = new LinkedHashMap<>();
            for (VtuzxMap inStock : inStockQuery) {
                Map<String, Object> prdInStockMap = new LinkedHashMap<>();
                String inStockEntryId = VtuzxUtil.getString(inStock, "FEntity_FEntryID");
                String fMaterialNo = VtuzxUtil.getString(inStock, "FMaterialId.FNumber");
                String fBatchNo = VtuzxUtil.getString(inStock, "FLot.FNumber");
                double FMustQty = VtuzxUtil.getDouble(inStock, "FMustQty");
                prdInStockMap.put("FEntryID", inStockEntryId);
                prdInStockMap.put("FMaterialId", new VtuzxMap("FNumber", fMaterialNo));
                prdInStockMap.put("FBatchNo", new VtuzxMap("FNumber", fBatchNo));
                prdInStockMap.put("FMustQty", FMustQty);
                prdInStockList.add(prdInStockMap);
            }

            //查询生产入库
            List<Document> prdInDetailList = new ArrayList<>();
//            Document prdInDoc = prdInDao.findOne(Criteria.where("taskBillNo").is(taskBillNo));
//            String inStockBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
            Iterator<Document> prdInItr = prdInDao.findList(Criteria.where("taskBillNo").is(taskBillNo).and("task").is(true), null, 0, 0);
            List<String> billNoList = new ArrayList<>();
            Date prdInTime = null;//入库日期
            while (prdInItr.hasNext()) {
                Document prdInDoc = prdInItr.next();
                prdInTime = VtuzxUtil.getObject(prdInDoc, "createTime");
                String inStockBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
                billNoList.add(inStockBillNo);
            }
            Iterator<Document> prdInDetailItr = prdInDetailDao.findList(Criteria.where("billNo").in(billNoList).and("syncKingdee").ne(true), null, 0, 0);
            while (prdInDetailItr.hasNext()) {
                Document prdInDetailDoc = prdInDetailItr.next();
                prdInDetailList.add(prdInDetailDoc);
            }

            //处理要修改的入库数据
            for (Map<String, Object> prdInStock : prdInStockList) {
                VtuzxMap FMaterialId = VtuzxUtil.getObject(prdInStock, "FMaterialId");
                VtuzxMap fBatch = VtuzxUtil.getObject(prdInStock, "FBatchNo");
                String fMaterial = VtuzxUtil.getString(FMaterialId, "FNumber");
                String fBatchNo = VtuzxUtil.getString(fBatch, "FNumber");
                double FMustQty = VtuzxUtil.getDouble(prdInStock, "FMustQty");
                for (Document prdInDetail : prdInDetailList) {
                    String dMaterialNo = VtuzxUtil.getString(prdInDetail, "materialNo");
                    String dStockNo = VtuzxUtil.getString(prdInDetail, "stockNo");
                    String dBatchNo = VtuzxUtil.getString(prdInDetail, "batchNo");
                    double count = VtuzxUtil.getDouble(prdInDetail, "count");
                    String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdInDetail, "createTime"));
                    //存在批号物料相同入了两个仓库，加一个数量判断
                    //&& FMustQty == count
                    if (fMaterial.equals(dMaterialNo) && fBatchNo.equals(dBatchNo)) {
                        prdInStock.put("fStockId", new VtuzxMap("FNumber", dStockNo));

                        if (!"Invalid Date".equals(orderPrdInTime)) {
                            prdInStockModel.put("FDate", orderPrdInTime);
                        } else {
                            prdInStockModel.put("FDate", createTime);
                        }
                        prdInStockModel.put("F_scrkd_ZTRKSJ", createTime);

//                    prdInStock.put("FLot", new VtuzxMap("FNumber", dBatchNo));
                    }
                }
            }


            prdInStockModel.put("FID", prdToInStockId);
            prdInStockModel.put("FEntity", prdInStockList);
//            if(!"Invalid Date".equals(orderPrdInTime)){
//                prdInStockModel.put("FDate",orderPrdInTime);
//            } else {
//                prdInStockModel.put("FDate",createTime);
//            }

            prdInStockModel.put("F_scrkd_ZTRKR", createUserName);
//            prdInStockModel.put("F_scrkd_ZTRKSJ", prdInTime);
            prdInStockModel.put("F_scrkd_ZTDJH", billNo);
            prdInStockModel.put("F_scrkd_SJLY", source);

            prdInStockParam.put("NeedUpDateFields", new ArrayList<>());
            prdInStockParam.put("NeedReturnFields", new ArrayList<>());
            prdInStockParam.put("IsDeleteEntry", false);
            prdInStockParam.put("SubSystemId", "");
            prdInStockParam.put("IsVerifyBaseDataField", false);
            prdInStockParam.put("IsEntryBatchFill", true);
            prdInStockParam.put("ValidateFlag", true);
            prdInStockParam.put("NumberSearch", true);
            prdInStockParam.put("InterationFlags", "");
            prdInStockParam.put("Model", prdInStockModel);
            param.append("PRD_INSTOCK", prdInStockParam);
            List<VtuzxMap> inStockList = kingdeeService.save(client, "PRD_INSTOCK", prdInStockParam);
            VtuzxMap inStock = inStockList.get(0);
            String prdToInStockBillNumber = VtuzxUtil.getString(inStock, "Number");
            kingdeeService.submit(client, "PRD_INSTOCK", "0", prdToInStockBillNumber);
            kingdeeService.audit(client, "PRD_INSTOCK", "0", prdToInStockBillNumber, "STK_InvCheckResult");
            historyDoc.append("kingdeeNumber", prdToInStockBillNumber);
            historyDoc.append("prdInStock", true);
        }

    }

    //分选入库BN
    private void syncPrdInStockOrderSortingInnerBn(Document historyDoc) throws Exception {
        Document prdIn = VtuzxUtil.getObject(historyDoc, "data");
        String orderPrdInTime = VtuzxUtil.getString(historyDoc, "prdInTime");//手动选择的入库日期
        String createUserName = VtuzxUtil.getString(prdIn, "createUserName");
        //String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdIn, "createTime"));
        String taskBillNo = VtuzxUtil.getString(prdIn, "taskBillNo");
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdeeYX();
        List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                        "FBillNo"
                ),
                String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(prdOrderQuery)) return;
        List<String> prdBillNoList = new ArrayList<>();
        for (VtuzxMap prdOrderMap : prdOrderQuery) {
            String kingdeeBillNo = VtuzxUtil.getString(prdOrderMap, "FBillNo");
            prdBillNoList.add(kingdeeBillNo);
        }
        //用生产订单下推生产入库
        Map<String, Object> prdToInStockMap = new LinkedHashMap<>();
        prdToInStockMap.put("Ids", "");
        prdToInStockMap.put("Numbers", prdBillNoList);
        prdToInStockMap.put("EntryIds", "");
        prdToInStockMap.put("RuleId", VtuzxUtil.getString(prdPushRuleDao.findOne(Criteria
                .where("ruleName").is("MOPushINSTOCK")
                .and("ruleType").is("sorting")
                .and("tokenType").is("kingdee3")
        ), "ruleId"));
        prdToInStockMap.put("TargetBillTypeId", "");
        prdToInStockMap.put("TargetOrgId", 0);
        prdToInStockMap.put("IsEnableDefaultRule", false);
        prdToInStockMap.put("IsDraftWhenSaveFail", false);
        prdToInStockMap.put("CustomParams", new VtuzxMap());
        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        param.append("PRD_MO", prdToInStockMap);
        List<VtuzxMap> prdToInStockList = kingdeeService.push(client, "PRD_MO", prdToInStockMap);
//        VtuzxMap prdToInStocks = prdToInStockList.get(0);
        for (VtuzxMap prdToInStocks : prdToInStockList) {
            String prdToInStockBillNo = VtuzxUtil.getString(prdToInStocks, "Number");
            String prdToInStockId = VtuzxUtil.getString(prdToInStocks, "Id");
            //修改生产入库
            List<VtuzxMap> inStockQuery = kingdeeService.query(client, "PRD_INSTOCK", new VtuzxArrayList<>(
                            "FBillNo",
                            "FEntity_FEntryID",
                            "FMaterialId.FNumber",
                            "FLot.FNumber",//批次号
                            "FMustQty"
                    ),
                    String.format("FBillNo = '%s'", prdToInStockBillNo), null, 0, 1);
            if (VtuzxUtil.isEmpty(inStockQuery)) return;
            List<Map<String, Object>> prdInStockList = new ArrayList<>();//金蝶
            Map<String, Object> prdInStockParam = new LinkedHashMap<>();
            Map<String, Object> prdInStockModel = new LinkedHashMap<>();
            for (VtuzxMap inStock : inStockQuery) {
                Map<String, Object> prdInStockMap = new LinkedHashMap<>();
                String inStockEntryId = VtuzxUtil.getString(inStock, "FEntity_FEntryID");
                String fMaterialNo = VtuzxUtil.getString(inStock, "FMaterialId.FNumber");
                String fBatchNo = VtuzxUtil.getString(inStock, "FLot.FNumber");
                double FMustQty = VtuzxUtil.getDouble(inStock, "FMustQty");
                prdInStockMap.put("FEntryID", inStockEntryId);
                prdInStockMap.put("FMaterialId", new VtuzxMap("FNumber", fMaterialNo));
                prdInStockMap.put("FBatchNo", new VtuzxMap("FNumber", fBatchNo));
                prdInStockMap.put("FMustQty", FMustQty);
                prdInStockList.add(prdInStockMap);
            }
            //查询生产入库
            List<Document> validDetails = (List<Document>) historyDoc.get("filteredDetails");
            List<Document> prdInDetailList = new ArrayList<>(validDetails);
//            Document prdInDoc = prdInDao.findOne(Criteria.where("taskBillNo").is(taskBillNo));
//            String inStockBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
            Iterator<Document> prdInItr = prdInDao.findList(Criteria.where("taskBillNo").is(taskBillNo).and("task").is(true), null, 0, 0);
            List<String> billNoList = new ArrayList<>();
            Date prdInTime = null;//入库日期
            while (prdInItr.hasNext()) {
                Document prdInDoc = prdInItr.next();
                prdInTime = VtuzxUtil.getObject(prdInDoc, "createTime");
                String inStockBillNo = VtuzxUtil.getString(prdInDoc, "billNo");
                billNoList.add(inStockBillNo);
            }
            Iterator<Document> prdInDetailItr = prdInDetailDao.findList(Criteria.where("billNo").in(billNoList).and("syncKingdee").ne(true), null, 0, 0);
            while (prdInDetailItr.hasNext()) {
                Document prdInDetailDoc = prdInDetailItr.next();
                prdInDetailList.add(prdInDetailDoc);
            }
            //处理要修改的入库数据
            for (Map<String, Object> prdInStock : prdInStockList) {
                VtuzxMap FMaterialId = VtuzxUtil.getObject(prdInStock, "FMaterialId");
                VtuzxMap fBatch = VtuzxUtil.getObject(prdInStock, "FBatchNo");
                String fMaterial = VtuzxUtil.getString(FMaterialId, "FNumber");
                String fBatchNo = VtuzxUtil.getString(fBatch, "FNumber");
                double FMustQty = VtuzxUtil.getDouble(prdInStock, "FMustQty");
                for (Document prdInDetail : prdInDetailList) {
                    String dMaterialNo = VtuzxUtil.getString(prdInDetail, "materialNo");
                    String dStockNo = VtuzxUtil.getString(prdInDetail, "stockNo");
                    String dBatchNo = VtuzxUtil.getString(prdInDetail, "batchNo");
                    double count = VtuzxUtil.getDouble(prdInDetail, "count");
                    String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(prdInDetail, "createTime"));
                    //存在批号物料相同入了两个仓库，加一个数量判断
                    //&& FMustQty == count
                    if (fMaterial.equals(dMaterialNo) && fBatchNo.equals(dBatchNo)) {
                        /*prdInStock.put("fStockId", new VtuzxMap("FNumber", dStockNo));*/
                        /*if(CP_WAREHOUSECODE.contains(dStockNo)){
                            prdInStock.put("fStockId", new VtuzxMap("FNumber", "001"));
                        } else{
                            prdInStock.put("fStockId", new VtuzxMap("FNumber", "002"));
                        }*/
                        //20251014生产成品“委外库”
                        prdInStock.put("fStockId", new VtuzxMap("FNumber", "002"));
                        prdInStock.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                        if (!"Invalid Date".equals(orderPrdInTime)) {
                            prdInStockModel.put("FDate", orderPrdInTime);
                        } else {
                            prdInStockModel.put("FDate", createTime);
                        }
                        /*20251015===日期*/
                        /*prdInStockModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));*/
                        prdInStockModel.put("F_scrkd_ZTRKSJ", createTime);
//                    prdInStock.put("FLot", new VtuzxMap("FNumber", dBatchNo));
                    }
                }
            }
            prdInStockModel.put("FID", prdToInStockId);
            prdInStockModel.put("FEntity", prdInStockList);
//            if(!"Invalid Date".equals(orderPrdInTime)){
//                prdInStockModel.put("FDate",orderPrdInTime);
//            } else {
//                prdInStockModel.put("FDate",createTime);
//            }
            prdInStockModel.put("F_scrkd_ZTRKR", createUserName);
//            prdInStockModel.put("F_scrkd_ZTRKSJ", prdInTime);
            prdInStockModel.put("F_scrkd_ZTDJH", billNo);
            prdInStockModel.put("F_scrkd_SJLY", source);
            prdInStockParam.put("NeedUpDateFields", new ArrayList<>());
            prdInStockParam.put("NeedReturnFields", new ArrayList<>());
            prdInStockParam.put("IsDeleteEntry", false);
            prdInStockParam.put("SubSystemId", "");
            prdInStockParam.put("IsVerifyBaseDataField", false);
            prdInStockParam.put("IsEntryBatchFill", true);
            prdInStockParam.put("ValidateFlag", true);
            prdInStockParam.put("NumberSearch", true);
            prdInStockParam.put("InterationFlags", "");
            prdInStockParam.put("Model", prdInStockModel);
            param.append("PRD_INSTOCK", prdInStockParam);
            List<VtuzxMap> inStockList = kingdeeService.save(client, "PRD_INSTOCK", prdInStockParam);
            VtuzxMap inStock = inStockList.get(0);
            String prdToInStockBillNumber = VtuzxUtil.getString(inStock, "Number");
            kingdeeService.submit(client, "PRD_INSTOCK", "0", prdToInStockBillNumber);
            kingdeeService.audit(client, "PRD_INSTOCK", "0", prdToInStockBillNumber, "STK_InvCheckResult");
            historyDoc.append("kingdeeNumber", prdToInStockBillNumber);
            historyDoc.append("prdInStock", true);
        }
    }


    @Override
    public void syncPrdReplenishment(ObjectId userId, String name, String billNo, String source, String supplementTime) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        Document prdSupplementOrderDoc = materialBomSupplementDao.findOne(Criteria.where("billNo").is(billNo));
        int boxCount = VtuzxUtil.getInt(prdSupplementOrderDoc, "boxCount");
        if (boxCount == 0) {
            historyDoc.append("prdReplenishment", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }

        historyDoc.append("billNo", billNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", prdSupplementOrderDoc);
        historyDoc.append("event", "prdReplenishment");
        try {
            syncPrdReplenishmentInner(historyDoc, supplementTime);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdReplenishment", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    @Override
    /*public void syncPrdReplenishmentBn(ObjectId userId, String name, String billNo, String source, String supplementTime) throws Exception {*/
    public void syncPrdReplenishmentBn(ObjectId userId, String name, List<Document> supplementList, String source, String supplementTime) throws Exception {
        List<Document> validDetails = new ArrayList<>();
        Document historyDoc = new Document();
        ObjectId id = null;
        String billNo = "";
        Document prdSupplementOrderDoc = new Document();
        for (Document supplementDoc : supplementList) {
            // 获取补料单据的单据编号
            billNo = VtuzxUtil.getString(supplementDoc, "billNo");
            historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
            if (historyDoc == null) {
                historyDoc = new Document("billNo", billNo);
            } else {
                id = VtuzxUtil.getObject(historyDoc, "_id");
            }
            prdSupplementOrderDoc = materialBomSupplementDao.findOne(Criteria.where("billNo").is(billNo));
            /*int boxCount = VtuzxUtil.getInt(prdSupplementOrderDoc, "boxCount");*/
            Iterator<Document> supplementDetailItr = materialBomSupplementDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
            while (supplementDetailItr.hasNext()) {
                Document detail = supplementDetailItr.next();
                String batchNo = VtuzxUtil.getString(detail, "batchNo");
                /*if (batchNo != null && batchNo.toUpperCase().startsWith("BN")) {*/
                if (batchNo.toUpperCase().startsWith("BN")) {
                    validDetails.add(detail);
                }
            }
        }
        //基于过滤后的明细计算有效分录数
        int validBoxCount = validDetails.size();
        if (validBoxCount == 0) {
            historyDoc.append("prdReplenishment", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                historyDoc.append("filteredDetails", validDetails);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }
        historyDoc.append("billNo", billNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", prdSupplementOrderDoc);
        historyDoc.append("event", "prdReplenishment");
        historyDoc.append("filteredDetails", validDetails);
        try {
            syncPrdReplenishmentInnerBn(historyDoc, supplementTime);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdReplenishment", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    //生产补料单
    private void syncPrdReplenishmentInner(Document historyDoc, String supplementTime) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        Document data = VtuzxUtil.getObject(historyDoc, "data");
        String repBillNo = VtuzxUtil.getString(data, "billNo");
        String taskBillNo = VtuzxUtil.getString(data, "taskBillNo");
        String createUserName = VtuzxUtil.getString(data, "createUserName");
        String createTime = VtuzxUtil.formatYmdF(VtuzxUtil.getObject(data, "createTime"));
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String produceHouseNo = VtuzxUtil.getString(prdTaskDoc, "produceHouseNo");

        //查询金蝶部门
        List<VtuzxMap> departmentQuery = kingdeeService.query(client, "BD_Department", new VtuzxArrayList<>(
                        "FNumber1",
                        "FNumber"
                ),
                String.format("FNumber1 = '%s'", produceHouseNo), null, 0, 1);
        if (VtuzxUtil.isEmpty(departmentQuery)) {
            throw new VtuzxException(String.format("部门[%s]在金蝶中不存在", produceHouseNo));
        }
        String department = VtuzxUtil.getString(departmentQuery.get(0), "FNumber");

        Document taskDetailDoc = prdTaskDetailDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String taskMaterialNo = VtuzxUtil.getString(taskDetailDoc, "materialNo");

        //任务单号查询生产订单
        List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                        "FBillNo",
                        "FQty"
                ),
                String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 1);

        if (VtuzxUtil.isEmpty(prdOrderQuery)) return;
        String kingdeeBillNo = VtuzxUtil.getString(prdOrderQuery.get(0), "FBillNo");

        //生产订单号查询用料清单
        List<VtuzxMap> materialBomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                        "FID",
                        "FBillNo",
                        "FMOBillNO",
                        "FMaterialID2.FNumber",
                        "FUnitID2.FNumber",
                        "FNeedQty2",
                        "FEntity_FEntryID",
                        "FMOEntryID"
                ),
                String.format("FMOBillNO = '%s'", kingdeeBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialBomQuery)) return;
        String fBillNo = VtuzxUtil.getString(materialBomQuery.get(0), "FBillNo");
        String fMOEntryID = VtuzxUtil.getString(materialBomQuery.get(0), "FMOEntryID");
        String entryID = VtuzxUtil.getString(materialBomQuery.get(0), "FEntity_FEntryID");


        //用料清单下推生产补料
        List<String> bomNumberList = new ArrayList<>();
        bomNumberList.add(fBillNo);
        Map<String, Object> bomToPickMap = new LinkedHashMap<>();
        bomToPickMap.put("Ids", "");
        bomToPickMap.put("Numbers", bomNumberList);
        bomToPickMap.put("EntryIds", "");
        bomToPickMap.put("RuleId", "ora_PRD_PPBOM2FEEDMTRL_ZY");
        bomToPickMap.put("TargetBillTypeId", "");
        bomToPickMap.put("TargetOrgId", 0);
        bomToPickMap.put("TargetFormId", "");
        bomToPickMap.put("IsEnableDefaultRule", false);
        bomToPickMap.put("IsDraftWhenSaveFail", false);
        bomToPickMap.put("CustomParams", new VtuzxMap());
        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        param.append("PRD_PPBOM", bomToPickMap);

        List<VtuzxMap> repairBillList = kingdeeService.push(client, "PRD_PPBOM", bomToPickMap);
        VtuzxMap repairBillMap = repairBillList.get(0);
        String kingdeeRepairBillNo = VtuzxUtil.getString(repairBillMap, "Number");


        //生产补料单号查询补料单
        List<VtuzxMap> repairOrderQuery = kingdeeService.query(client, "PRD_FeedMtrl", new VtuzxArrayList<>(
                        "FID",
                        "FEntity_FEntryID",
                        "FMaterialId.FNumber"
                ),
                String.format("FBillNo = '%s'", kingdeeRepairBillNo), null, 0, 1);

        if (VtuzxUtil.isEmpty(repairOrderQuery)) return;
        String fid = VtuzxUtil.getString(repairOrderQuery.get(0), "FID");
        String entryId = VtuzxUtil.getString(repairOrderQuery.get(0), "FEntity_FEntryID");


        Map<String, Object> prdRepairOrderParam = new LinkedHashMap<>();
        Map<String, Object> prdRepairOrderModel = new LinkedHashMap<>();
        List<Map<String, Object>> fRepairEntry = new ArrayList<>();

        //留一个原单据的分录
        materialPickInner(repairOrderQuery.get(0), fRepairEntry);

        List<String> materialNoList = new ArrayList<>();
        List<Document> prdSupplementOrderList = new ArrayList<>();
        Iterator<Document> prdSupplementOrderItr = materialBomSupplementDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (prdSupplementOrderItr.hasNext()) {
            Document prdSupplementOrderDoc = prdSupplementOrderItr.next();
            String materialNo = VtuzxUtil.getString(prdSupplementOrderDoc, "materialNo");
            materialNoList.add(materialNo);
            prdSupplementOrderList.add(prdSupplementOrderDoc);
        }
        //查即时库存 库存不够补其他入库
        String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
        List<VtuzxMap> inventoryQuery = kingdeeService.query(client, "STK_Inventory", new VtuzxArrayList<>(
                        "FLot.FNumber",
                        "FMaterialId.FNumber",
                        "FStockId.FNumber",
                        "FBaseQty"
                ),
                String.format("FMaterialId.FNumber in (%s) and FBaseQty != 0", materialNoCond), null, 0, 0);


        for (Document prdSupplementOrder : prdSupplementOrderList) {
            Map<String, Object> repairMap = new LinkedHashMap<>();
            String materialNo = VtuzxUtil.getString(prdSupplementOrder, "materialNo");
            String stockNo = VtuzxUtil.getString(prdSupplementOrder, "stockNo");
            String batchNo = VtuzxUtil.getString(prdSupplementOrder, "batchNo");
            String unitName = VtuzxUtil.getString(prdSupplementOrder, "unit");
            double count = VtuzxUtil.getDouble(prdSupplementOrder, "count");

            //判断单位是汉字还是拼音
            Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
            Matcher m = p.matcher(unitName);
            String unit = "";
            if (!m.find()) {//不是汉字
                //查询单位编码，直接传文字无效
                String cond = String.format("FNumber = '%s'", unitName);
                List<VtuzxMap> bd_customer = kingdeeService.query(client, "BD_UNIT", new VtuzxArrayList<>(
                        "FNumber",//单位编码
                        "FNAME"//单位名称
                ), cond);

                if (bd_customer != null && bd_customer.size() > 0) {
                    unit = bd_customer.get(0).getString("FNumber");
                }
            } else {//如果是汉字
                String cond = String.format("FName = '%s'", unitName);
                List<VtuzxMap> bd_customer = kingdeeService.query(client, "BD_UNIT", new VtuzxArrayList<>(
                        "FNumber",//单位编码
                        "FNAME"//单位名称
                ), cond);

                if (bd_customer != null && bd_customer.size() > 0) {
                    unit = bd_customer.get(0).getString("FNumber");
                }
            }


            //存新分录
            repairMap.put("FParentMaterialId", new VtuzxMap("FNumber", taskMaterialNo));
            repairMap.put("FReserveType", "1");
            repairMap.put("FBaseStockActualQty", count);
            repairMap.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
            repairMap.put("FUnitID", new VtuzxMap("FNumber", unit));
            repairMap.put("FAppQty", count);
            repairMap.put("FActualQty", count);
            repairMap.put("FEntryVmiBusiness", false);
            repairMap.put("FStockId", new VtuzxMap("FNumber", stockNo));
            repairMap.put("FLot", new VtuzxMap("FNumber", batchNo));
            repairMap.put("FFeedReasonId", new VtuzxMap("FNumber", "BLYY01_SYS"));
            repairMap.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
            repairMap.put("FMoBillNo", kingdeeBillNo);
            repairMap.put("FMoEntryId", fMOEntryID);
            repairMap.put("FOwnerTypeId", "BD_OwnerOrg");
            repairMap.put("FStockAppQty", count);
            repairMap.put("FStockActualQty", count);
            repairMap.put("FMoId", 100287);
            repairMap.put("FMoEntrySeq", 1);
            repairMap.put("FBaseAppQty", count);
            repairMap.put("FPPBomBillNo", fBillNo);
            repairMap.put("FBaseUnitId", new VtuzxMap("FNumber", unit));
            repairMap.put("FStockUnitId", new VtuzxMap("FNumber", unit));
            repairMap.put("FEntryWorkShopId", new VtuzxMap("FNumber", department));
            repairMap.put("FBaseActualQty", count);
            repairMap.put("FKeeperTypeId", "BD_KeeperOrg");
            repairMap.put("FKeeperId", new VtuzxMap("FNumber", "100"));
            repairMap.put("FOwnerId", new VtuzxMap("FNumber", "100"));
            //用补料物料和用料清单物料判断，如果物料相同就补到该条分录上，如果无法匹配就默认补到第一条
            boolean isEquals = false;
            for (VtuzxMap repairOrder : repairOrderQuery) {
                String material = VtuzxUtil.getString(repairOrder, "FMaterialId.FNumber");
                String fEntryID = VtuzxUtil.getString(repairOrder, "FEntryID");
                if (materialNo.equals(material)) {
                    repairMap.put("FEntrySrcInterId", fEntryID);
                    isEquals = true;
                }
            }
            if (!isEquals) {
                repairMap.put("FEntrySrcInterId", entryID);
            }
            repairMap.put("FEntrySrcBillType", "PRD_PPBOM");
            repairMap.put("FEntrySrcBillNo", fBillNo);
            repairMap.put("FParentOwnerTypeId", "BD_OwnerOrg");
            repairMap.put("FParentOwnerId", new VtuzxMap("FNumber", "100"));
            fRepairEntry.add(repairMap);
        }
        prdRepairOrderModel.put("FID", fid);
        prdRepairOrderModel.put("FWorkShopId", new VtuzxMap("FNumber", department));
        if (!VtuzxUtil.isEmpty(supplementTime) && !"Invalid Date".equals(supplementTime)) {
            prdRepairOrderModel.put("FDate", supplementTime);
        } else {
            prdRepairOrderModel.put("FDate", createTime);
        }

        prdRepairOrderModel.put("F_scbld_ZTBLR", createUserName);
        prdRepairOrderModel.put("F_scbld_ZTDJH", repBillNo);
        prdRepairOrderModel.put("F_scbld_SJLY", source);
        prdRepairOrderModel.put("F_scbld_ZTBLSJ", createTime);
        prdRepairOrderModel.put("FEntity", fRepairEntry);

        List<Document> depDocList = new ArrayList<>();
        //判断要补的物料的即时库存是否足够，如果不够，做其他入库
        for (Map<String, Object> prdSupplement : prdSupplementOrderList) {
            boolean no = false;
            String materialNo = VtuzxUtil.getString(prdSupplement, "materialNo");
            String batchNo = VtuzxUtil.getString(prdSupplement, "batchNo");
            String stockNo = VtuzxUtil.getString(prdSupplement, "stockNo");
            double count = VtuzxUtil.getDouble(prdSupplement, "count");
            for (VtuzxMap inventory : inventoryQuery) {
                String fMaterialId_FNumber = VtuzxUtil.getString(inventory, "FMaterialId.FNumber");
                String fLot_FNumber = VtuzxUtil.getString(inventory, "FLot.FNumber");
                String fStockId_FNumber = VtuzxUtil.getString(inventory, "FStockId.FNumber");
                double qty = VtuzxUtil.getDouble(inventory, "FBaseQty");
                if (materialNo.equals(fMaterialId_FNumber) && batchNo.equals(fLot_FNumber) && stockNo.equals(fStockId_FNumber)) {
                    no = true;
                    if (qty < count) {
                        Document document = new Document("materialNo", materialNo)
                                .append("batchNo", batchNo)
                                .append("stockNo", stockNo)
                                .append("count", count - qty);
                        depDocList.add(document);
                    }
                }
            }
            if (!no) {
                depDocList.add(new Document("materialNo", materialNo)
                        .append("batchNo", batchNo)
                        .append("stockNo", stockNo)
                        .append("count", count));
            }
        }
        if (depDocList.size() != 0) {
            otherInInner(client, depDocList, null, billNo, param);
        }

        prdRepairOrderParam.put("NeedUpDateFields", new ArrayList<>());
        prdRepairOrderParam.put("NeedReturnFields", new ArrayList<>());
        prdRepairOrderParam.put("IsDeleteEntry", true);
        prdRepairOrderParam.put("SubSystemId", "");
        prdRepairOrderParam.put("IsVerifyBaseDataField", false);
        prdRepairOrderParam.put("IsEntryBatchFill", true);
        prdRepairOrderParam.put("ValidateFlag", true);
        prdRepairOrderParam.put("NumberSearch", true);
        prdRepairOrderParam.put("InterationFlags", "");
        prdRepairOrderParam.put("Model", prdRepairOrderModel);
        param.append("PRD_FeedMtrl", prdRepairOrderParam);
        List<VtuzxMap> repairList = kingdeeService.save(client, "PRD_FeedMtrl", prdRepairOrderParam);
        String repairNumber = VtuzxUtil.getString(repairList.get(0), "Number");


        List<VtuzxMap> repairOrderTwoQuery = kingdeeService.query(client, "PRD_FeedMtrl", new VtuzxArrayList<>(
                        "FID",
                        "FEntity_FEntryID",
                        "FMaterialId.FNumber"
                ),
                String.format("FBillNo = '%s'", repairNumber), null, 0, 0);

        if (VtuzxUtil.isEmpty(repairOrderTwoQuery)) return;
        List<Map<String, Object>> entryIdList = new ArrayList<>();
        for (VtuzxMap repairOrderTwo : repairOrderTwoQuery) {
            Map<String, Object> map = new LinkedHashMap<>();
            String fEntryID = VtuzxUtil.getString(repairOrderTwo, "FEntity_FEntryID");
            if (!fEntryID.equals(entryId)) {
                map.put("FEntryID", fEntryID);
                entryIdList.add(map);
            }
        }

        Map<String, Object> prdRepairOrderTwoParam = new LinkedHashMap<>();
        Map<String, Object> prdRepairOrderTwoModel = new LinkedHashMap<>();

        prdRepairOrderTwoModel.put("FID", fid);
        prdRepairOrderTwoModel.put("FEntity", entryIdList);

        prdRepairOrderTwoParam.put("NeedUpDateFields", new ArrayList<>());
        prdRepairOrderTwoParam.put("NeedReturnFields", new ArrayList<>());
        prdRepairOrderTwoParam.put("IsDeleteEntry", true);
        prdRepairOrderTwoParam.put("SubSystemId", "");
        prdRepairOrderTwoParam.put("IsVerifyBaseDataField", true);
        prdRepairOrderTwoParam.put("IsEntryBatchFill", false);
        prdRepairOrderTwoParam.put("ValidateFlag", true);
        prdRepairOrderTwoParam.put("NumberSearch", true);
        prdRepairOrderTwoParam.put("InterationFlags", "");
        prdRepairOrderTwoParam.put("Model", prdRepairOrderTwoModel);

        param.append("PRD_FeedMtrl", prdRepairOrderTwoParam);

        try {
            List<VtuzxMap> PRD_FeedMtrlList = kingdeeService.save(client, "PRD_FeedMtrl", prdRepairOrderTwoParam);
            VtuzxMap feedMtrlMap = PRD_FeedMtrlList.get(0);
            String number = VtuzxUtil.getString(feedMtrlMap, "Number");
            kingdeeService.submit(client, "PRD_FeedMtrl", "0", number);
            kingdeeService.audit(client, "PRD_FeedMtrl", "0", number, "STK_InvCheckResult");
            historyDoc.append("kingdeeNumber", number);
            historyDoc.append("prdReplenishment", true);
        } catch (Exception e) {
            _logger.info(e.getMessage());
        }
    }

    //生产补料单BN
    private void syncPrdReplenishmentInnerBn(Document historyDoc, String supplementTime) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdeeYX();
        Document data = VtuzxUtil.getObject(historyDoc, "data");
        String repBillNo = VtuzxUtil.getString(data, "billNo");
        String taskBillNo = VtuzxUtil.getString(data, "taskBillNo");
        String createUserName = VtuzxUtil.getString(data, "createUserName");
        String createTime = VtuzxUtil.formatYmdF(VtuzxUtil.getObject(data, "createTime"));
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String produceHouseNo = VtuzxUtil.getString(prdTaskDoc, "produceHouseNo");
        //查询金蝶部门
        /*List<VtuzxMap> departmentQuery = kingdeeService.query(client, "BD_Department", new VtuzxArrayList<>(
                        "FNumber1",
                        "FNumber"
                ),
                String.format("FNumber1 = '%s'", produceHouseNo), null, 0, 1);
        if (VtuzxUtil.isEmpty(departmentQuery)) {
            throw new VtuzxException(String.format("部门[%s]在金蝶中不存在", produceHouseNo));
        }
        String department = VtuzxUtil.getString(departmentQuery.get(0), "FNumber");*/
        Document taskDetailDoc = prdTaskDetailDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String taskMaterialNo = VtuzxUtil.getString(taskDetailDoc, "materialNo");
        //任务单号查询生产订单
        List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                        "FBillNo",
                        "FQty"
                ),
                String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 1);
        if (VtuzxUtil.isEmpty(prdOrderQuery)) return;
        String kingdeeBillNo = VtuzxUtil.getString(prdOrderQuery.get(0), "FBillNo");
        //生产订单号查询用料清单
        List<VtuzxMap> materialBomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                        "FID",
                        "FBillNo",
                        "FMOBillNO",
                        "FMaterialID2.FNumber",
                        "FUnitID2.FNumber",
                        "FNeedQty2",
                        "FEntity_FEntryID",
                        "FMOEntryID"
                ),
                String.format("FMOBillNO = '%s'", kingdeeBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialBomQuery)) return;
        String fBillNo = VtuzxUtil.getString(materialBomQuery.get(0), "FBillNo");
        String fMOEntryID = VtuzxUtil.getString(materialBomQuery.get(0), "FMOEntryID");
        String entryID = VtuzxUtil.getString(materialBomQuery.get(0), "FEntity_FEntryID");
        //用料清单下推生产补料
        List<String> bomNumberList = new ArrayList<>();
        bomNumberList.add(fBillNo);
        Map<String, Object> bomToPickMap = new LinkedHashMap<>();
        bomToPickMap.put("Ids", "");
        bomToPickMap.put("Numbers", bomNumberList);
        bomToPickMap.put("EntryIds", "");
        bomToPickMap.put("RuleId", VtuzxUtil.getString(prdPushRuleDao.findOne(Criteria
                .where("ruleName").is("PPBOMPushFeedMtrl")
                .and("ruleType").is("product")
                .and("tokenType").is("kingdee3")
        ), "ruleId"));
        bomToPickMap.put("TargetBillTypeId", "");
        bomToPickMap.put("TargetOrgId", 0);
        bomToPickMap.put("TargetFormId", "");
        bomToPickMap.put("IsEnableDefaultRule", false);
        bomToPickMap.put("IsDraftWhenSaveFail", false);
        bomToPickMap.put("CustomParams", new VtuzxMap());
        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        param.append("PRD_PPBOM", bomToPickMap);
        List<VtuzxMap> repairBillList = kingdeeService.push(client, "PRD_PPBOM", bomToPickMap);
        VtuzxMap repairBillMap = repairBillList.get(0);
        String kingdeeRepairBillNo = VtuzxUtil.getString(repairBillMap, "Number");
        //生产补料单号查询补料单
        List<VtuzxMap> repairOrderQuery = kingdeeService.query(client, "PRD_FeedMtrl", new VtuzxArrayList<>(
                        "FID",
                        "FEntity_FEntryID",
                        "FMaterialId.FNumber"
                ),
                String.format("FBillNo = '%s'", kingdeeRepairBillNo), null, 0, 1);
        if (VtuzxUtil.isEmpty(repairOrderQuery)) return;
        String fid = VtuzxUtil.getString(repairOrderQuery.get(0), "FID");
        String entryId = VtuzxUtil.getString(repairOrderQuery.get(0), "FEntity_FEntryID");
        Map<String, Object> prdRepairOrderParam = new LinkedHashMap<>();
        Map<String, Object> prdRepairOrderModel = new LinkedHashMap<>();
        List<Map<String, Object>> fRepairEntry = new ArrayList<>();
        //留一个原单据的分录
        //20251105下推数据行
        //materialPickInner(repairOrderQuery.get(0), fRepairEntry);
        List<Document> validDetails = VtuzxUtil.getObject(historyDoc, "filteredDetails");
        List<String> materialNoList = new ArrayList<>();
        //使用过滤结果
        List<Document> prdSupplementOrderList = new ArrayList<>(validDetails);
        for (Document detail : validDetails) {
            materialNoList.add(VtuzxUtil.getString(detail, "materialNo"));
        }
        /*Iterator<Document> prdSupplementOrderItr = materialBomSupplementDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (prdSupplementOrderItr.hasNext()) {
            Document prdSupplementOrderDoc = prdSupplementOrderItr.next();
            String materialNo = VtuzxUtil.getString(prdSupplementOrderDoc, "materialNo");
            materialNoList.add(materialNo);
            prdSupplementOrderList.add(prdSupplementOrderDoc);
        }*/
        //查即时库存 库存不够补其他入库
        String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
        List<VtuzxMap> inventoryQuery = kingdeeService.query(client, "STK_Inventory", new VtuzxArrayList<>(
                        "FLot.FNumber",
                        "FMaterialId.FNumber",
                        "FStockId.FNumber",
                        "FBaseQty"
                ),
                String.format("FMaterialId.FNumber in (%s) and FBaseQty != 0", materialNoCond), null, 0, 0);
        for (Document prdSupplementOrder : prdSupplementOrderList) {
            Map<String, Object> repairMap = new LinkedHashMap<>();
            String materialNo = VtuzxUtil.getString(prdSupplementOrder, "materialNo");
            String stockNo = VtuzxUtil.getString(prdSupplementOrder, "stockNo");
            String batchNo = VtuzxUtil.getString(prdSupplementOrder, "batchNo");
            String unitName = VtuzxUtil.getString(prdSupplementOrder, "unit");
            double count = VtuzxUtil.getDouble(prdSupplementOrder, "count");
            //判断单位是汉字还是拼音
            Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
            Matcher m = p.matcher(unitName);
            String unit = "";
            if (!m.find()) {//不是汉字
                //查询单位编码，直接传文字无效
                String cond = String.format("FNumber = '%s'", unitName);
                List<VtuzxMap> bd_customer = kingdeeService.query(client, "BD_UNIT", new VtuzxArrayList<>(
                        "FNumber",//单位编码
                        "FNAME"//单位名称
                ), cond);
                if (bd_customer != null && bd_customer.size() > 0) {
                    unit = bd_customer.get(0).getString("FNumber");
                }
            } else {//如果是汉字
                String cond = String.format("FName = '%s'", unitName);
                List<VtuzxMap> bd_customer = kingdeeService.query(client, "BD_UNIT", new VtuzxArrayList<>(
                        "FNumber",//单位编码
                        "FNAME"//单位名称
                ), cond);

                if (bd_customer != null && bd_customer.size() > 0) {
                    unit = bd_customer.get(0).getString("FNumber");
                }
            }
            //存新分录
            repairMap.put("FParentMaterialId", new VtuzxMap("FNumber", taskMaterialNo));
            repairMap.put("FReserveType", "1");
            repairMap.put("FBaseStockActualQty", count);
            repairMap.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
            repairMap.put("FUnitID", new VtuzxMap("FNumber", unit));
            repairMap.put("FAppQty", count);
            repairMap.put("FActualQty", count);
            repairMap.put("FEntryVmiBusiness", false);
            /*repairMap.put("FStockId", new VtuzxMap("FNumber", stockNo));*/
            /*if(CP_WAREHOUSECODE.contains(stockNo)){
                repairMap.put("FStockId", new VtuzxMap("FNumber", "001"));
            } else{
                repairMap.put("FStockId", new VtuzxMap("FNumber", "002"));
            }*/
            //20251014生产成品“委外库”
            repairMap.put("FStockId", new VtuzxMap("FNumber", "002"));
            repairMap.put("FLot", new VtuzxMap("FNumber", batchNo));
            repairMap.put("FFeedReasonId", new VtuzxMap("FNumber", "BLYY01_SYS"));
            repairMap.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
            repairMap.put("FMoBillNo", kingdeeBillNo);
            repairMap.put("FMoEntryId", fMOEntryID);
            repairMap.put("FOwnerTypeId", "BD_OwnerOrg");
            repairMap.put("FStockAppQty", count);
            repairMap.put("FStockActualQty", count);
            repairMap.put("FMoId", 100287);
            repairMap.put("FMoEntrySeq", 1);
            repairMap.put("FBaseAppQty", count);
            repairMap.put("FPPBomBillNo", fBillNo);
            repairMap.put("FBaseUnitId", new VtuzxMap("FNumber", unit));
            repairMap.put("FStockUnitId", new VtuzxMap("FNumber", unit));
            repairMap.put("FEntryWorkShopId", new VtuzxMap("FNumber", "BM000004"));
            repairMap.put("FBaseActualQty", count);
            repairMap.put("FKeeperTypeId", "BD_KeeperOrg");
            repairMap.put("FKeeperId", new VtuzxMap("FNumber", "200"));
            repairMap.put("FOwnerId", new VtuzxMap("FNumber", "200"));
            //用补料物料和用料清单物料判断，如果物料相同就补到该条分录上，如果无法匹配就默认补到第一条
            boolean isEquals = false;
            for (VtuzxMap repairOrder : repairOrderQuery) {
                String material = VtuzxUtil.getString(repairOrder, "FMaterialId.FNumber");
                String fEntryID = VtuzxUtil.getString(repairOrder, "FEntryID");
                if (materialNo.equals(material)) {
                    repairMap.put("FEntrySrcInterId", fEntryID);
                    isEquals = true;
                }
            }
            if (!isEquals) {
                repairMap.put("FEntrySrcInterId", entryID);
            }
            repairMap.put("FEntrySrcBillType", "PRD_PPBOM");
            repairMap.put("FEntrySrcBillNo", fBillNo);
            repairMap.put("FParentOwnerTypeId", "BD_OwnerOrg");
            repairMap.put("FParentOwnerId", new VtuzxMap("FNumber", "200"));
            fRepairEntry.add(repairMap);
        }
        prdRepairOrderModel.put("FID", fid);
        prdRepairOrderModel.put("FWorkShopId", new VtuzxMap("FNumber", "BM000004"));
        if (!VtuzxUtil.isEmpty(supplementTime) && !"Invalid Date".equals(supplementTime)) {
            prdRepairOrderModel.put("FDate", supplementTime);
        } else {
            prdRepairOrderModel.put("FDate", createTime);
        }
        /*20251015===日期*/
        /*prdRepairOrderModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));*/
        prdRepairOrderModel.put("F_scbld_ZTBLR", createUserName);
        prdRepairOrderModel.put("F_scbld_ZTDJH", repBillNo);
        prdRepairOrderModel.put("F_scbld_SJLY", source);
        prdRepairOrderModel.put("F_scbld_ZTBLSJ", createTime);
        prdRepairOrderModel.put("FEntity", fRepairEntry);
        List<Document> depDocList = new ArrayList<>();
        //判断要补的物料的即时库存是否足够，如果不够，做其他入库
        for (Map<String, Object> prdSupplement : prdSupplementOrderList) {
            boolean no = false;
            String materialNo = VtuzxUtil.getString(prdSupplement, "materialNo");
            String batchNo = VtuzxUtil.getString(prdSupplement, "batchNo");
            String stockNo = VtuzxUtil.getString(prdSupplement, "stockNo");
            double count = VtuzxUtil.getDouble(prdSupplement, "count");
            for (VtuzxMap inventory : inventoryQuery) {
                String fMaterialId_FNumber = VtuzxUtil.getString(inventory, "FMaterialId.FNumber");
                String fLot_FNumber = VtuzxUtil.getString(inventory, "FLot.FNumber");
                String fStockId_FNumber = VtuzxUtil.getString(inventory, "FStockId.FNumber");
                double qty = VtuzxUtil.getDouble(inventory, "FBaseQty");
                if (materialNo.equals(fMaterialId_FNumber) && batchNo.equals(fLot_FNumber) && stockNo.equals(fStockId_FNumber)) {
                    no = true;
                    if (qty < count) {
                        Document document = new Document("materialNo", materialNo)
                                .append("batchNo", batchNo)
                                .append("stockNo", stockNo)
                                .append("count", count - qty);
                        depDocList.add(document);
                    }
                }
            }
            if (!no) {
                depDocList.add(new Document("materialNo", materialNo)
                        .append("batchNo", batchNo)
                        .append("stockNo", stockNo)
                        .append("count", count));
            }
        }
        if (depDocList.size() != 0) {
            otherInInnerBn(client, depDocList, null, billNo, param);
        }
        prdRepairOrderParam.put("NeedUpDateFields", new ArrayList<>());
        prdRepairOrderParam.put("NeedReturnFields", new ArrayList<>());
        prdRepairOrderParam.put("IsDeleteEntry", true);
        prdRepairOrderParam.put("SubSystemId", "");
        prdRepairOrderParam.put("IsVerifyBaseDataField", false);
        prdRepairOrderParam.put("IsEntryBatchFill", true);
        prdRepairOrderParam.put("ValidateFlag", true);
        prdRepairOrderParam.put("NumberSearch", true);
        prdRepairOrderParam.put("InterationFlags", "");
        prdRepairOrderParam.put("Model", prdRepairOrderModel);
        param.append("PRD_FeedMtrl", prdRepairOrderParam);
//        List<VtuzxMap> repairList = kingdeeService.save(client, "PRD_FeedMtrl", prdRepairOrderParam);
//        String repairNumber = VtuzxUtil.getString(repairList.get(0), "Number");
//        List<VtuzxMap> repairOrderTwoQuery = kingdeeService.query(client, "PRD_FeedMtrl", new VtuzxArrayList<>(
//                        "FID",
//                        "FEntity_FEntryID",
//                        "FMaterialId.FNumber"
//                ),
//                String.format("FBillNo = '%s'", repairNumber), null, 0, 0);
//        if (VtuzxUtil.isEmpty(repairOrderTwoQuery)) return;
//        List<Map<String, Object>> entryIdList = new ArrayList<>();
//        for (VtuzxMap repairOrderTwo : repairOrderTwoQuery) {
//            Map<String, Object> map = new LinkedHashMap<>();
//            String fEntryID = VtuzxUtil.getString(repairOrderTwo, "FEntity_FEntryID");
//            if (!fEntryID.equals(entryId)) {
//                map.put("FEntryID", fEntryID);
//                entryIdList.add(map);
//            }
//        }
//        Map<String, Object> prdRepairOrderTwoParam = new LinkedHashMap<>();
//        Map<String, Object> prdRepairOrderTwoModel = new LinkedHashMap<>();
//        prdRepairOrderTwoModel.put("FID", fid);
//        prdRepairOrderTwoModel.put("FEntity", entryIdList);
//        prdRepairOrderTwoParam.put("NeedUpDateFields", new ArrayList<>());
//        prdRepairOrderTwoParam.put("NeedReturnFields", new ArrayList<>());
//        prdRepairOrderTwoParam.put("IsDeleteEntry", true);
//        prdRepairOrderTwoParam.put("SubSystemId", "");
//        prdRepairOrderTwoParam.put("IsVerifyBaseDataField", true);
//        prdRepairOrderTwoParam.put("IsEntryBatchFill", false);
//        prdRepairOrderTwoParam.put("ValidateFlag", true);
//        prdRepairOrderTwoParam.put("NumberSearch", true);
//        prdRepairOrderTwoParam.put("InterationFlags", "");
//        prdRepairOrderTwoParam.put("Model", prdRepairOrderTwoModel);
//        param.append("PRD_FeedMtrl", prdRepairOrderTwoParam);
        try {
            System.out.println(prdRepairOrderParam);
            List<VtuzxMap> PRD_FeedMtrlList = kingdeeService.save(client, "PRD_FeedMtrl", prdRepairOrderParam);
            VtuzxMap feedMtrlMap = PRD_FeedMtrlList.get(0);
            String number = VtuzxUtil.getString(feedMtrlMap, "Number");
            kingdeeService.submit(client, "PRD_FeedMtrl", "0", number);
            kingdeeService.audit(client, "PRD_FeedMtrl", "0", number, "STK_InvCheckResult");
            historyDoc.append("kingdeeNumber", number);
            historyDoc.append("prdReplenishment", true);
        } catch (Exception e) {
            _logger.info(e.getMessage());
        }
    }

    @Override
    public void syncPrdReturn(ObjectId userId, String name, String billNo, String source) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        Document prdReturnOrderDoc = materialBomReturnDao.findOne(Criteria.where("billNo").is(billNo));
        int boxCount = VtuzxUtil.getInt(prdReturnOrderDoc, "boxCount");
        if (boxCount == 0) {
            historyDoc.append("prdReturnOrder", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }

        historyDoc.append("billNo", billNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", prdReturnOrderDoc);
        historyDoc.append("event", "prdReturn");
        try {
            syncPrdReturnInner(historyDoc);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdReturnOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    private void syncPrdReturnInner(Document historyDoc) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        Document data = VtuzxUtil.getObject(historyDoc, "data");
        String createUserName = VtuzxUtil.getString(data, "createUserName");
        String taskBillNo = VtuzxUtil.getString(data, "taskBillNo");
        String createTime = VtuzxUtil.formatYmdF(VtuzxUtil.getObject(data, "createTime"));
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");

        //任务单号查询生产订单
        List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                        "FBillNo",
                        "FQty"
                ),
                String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 1);

        if (VtuzxUtil.isEmpty(prdOrderQuery)) {
            throw new VtuzxException(String.format("金蝶不存在中台单据号为[%s]的生产订单", taskBillNo));
        }
        String kingdeeBillNo = VtuzxUtil.getString(prdOrderQuery.get(0), "FBillNo");

        //生产订单号查询用料清单
        List<VtuzxMap> materialBomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                        "FID",
                        "FBillNo",
                        "FMOBillNO",
                        "FMaterialID2.FNumber",
                        "FUnitID2.FNumber",
                        "FNeedQty2",
                        "FEntity_FEntryID"
                ),
                String.format("FMOBillNO = '%s'", kingdeeBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialBomQuery)) return;
        String fBillNo = VtuzxUtil.getString(materialBomQuery.get(0), "FBillNo");


        //用料清单下推生产退料
        List<String> bomNumberList = new ArrayList<>();
        bomNumberList.add(fBillNo);
        Map<String, Object> bomToPickMap = new LinkedHashMap<>();
        bomToPickMap.put("Ids", "");
        bomToPickMap.put("Numbers", bomNumberList);
        bomToPickMap.put("EntryIds", "");
        bomToPickMap.put("RuleId", "ora_PRD_PPBOM2RETURNMTRL_ZY");
        bomToPickMap.put("TargetBillTypeId", "");
        bomToPickMap.put("TargetOrgId", 0);
        bomToPickMap.put("TargetFormId", "");
        bomToPickMap.put("IsEnableDefaultRule", false);
        bomToPickMap.put("IsDraftWhenSaveFail", true);
        bomToPickMap.put("CustomParams", new VtuzxMap());

        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        param.append("PRD_PPBOM", bomToPickMap);
        List<VtuzxMap> returnBillList = kingdeeService.push(client, "PRD_PPBOM", bomToPickMap);
        VtuzxMap returnBillMap = returnBillList.get(0);
        String kingdeeReturnBillNo = VtuzxUtil.getString(returnBillMap, "Number");

        //生产退料单号查询退料单
        List<VtuzxMap> retuenOrderQuery = kingdeeService.query(client, "PRD_ReturnMtrl", new VtuzxArrayList<>(
                        "FID",
                        "FEntity_FEntryID",
                        "FMaterialId.FNumber",
                        "FLot.FNumber"
                ),
                String.format("FBillNo = '%s'", kingdeeReturnBillNo), null, 0, 0);

        if (VtuzxUtil.isEmpty(retuenOrderQuery)) return;
        String fid = VtuzxUtil.getString(retuenOrderQuery.get(0), "FID");

        Map<String, Object> prdReturnOrderParam = new LinkedHashMap<>();
        Map<String, Object> prdReturnOrderModel = new LinkedHashMap<>();

        List<Document> returnOrderList = new ArrayList<>();
        Iterator<Document> prdReturnOrderItr = materialBomReturnDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (prdReturnOrderItr.hasNext()) {
            Document prdReturnOrderDoc = prdReturnOrderItr.next();
            returnOrderList.add(prdReturnOrderDoc);
        }

        List<Map<String, Object>> fReturnEntry = new ArrayList<>();
        for (VtuzxMap returnOrder : retuenOrderQuery) {
            Map<String, Object> returnMap = new LinkedHashMap<>();
            String fEntity_FEntryID = VtuzxUtil.getString(returnOrder, "FEntity_FEntryID");
            String fMaterialNo = VtuzxUtil.getString(returnOrder, "FMaterialId.FNumber");
            String fFlot = VtuzxUtil.getString(returnOrder, "FLot.FNumber");
            for (Document returnOrderDoc : returnOrderList) {
                String materialNo = VtuzxUtil.getString(returnOrderDoc, "materialNo");
                String stockNo = VtuzxUtil.getString(returnOrderDoc, "stockNo");
                String batchNo = VtuzxUtil.getString(returnOrderDoc, "batchNo");
                double count = VtuzxUtil.getDouble(returnOrderDoc, "count");
                //存新分录
                if (fMaterialNo.equals(materialNo) && fFlot.equals(batchNo)) {
                    returnMap.put("FEntryID", fEntity_FEntryID);
                    returnMap.put("FAPPQty", count);
                    returnMap.put("FQty", count);
                    returnMap.put("FReturnType", "1");
                    returnMap.put("FStockId", new VtuzxMap("FNumber", stockNo));
                    returnMap.put("FLot", new VtuzxMap("FNumber", batchNo));
                    returnMap.put("FReserveType", "1");
                    returnMap.put("FBASESTOCKQTY", count);
                    returnMap.put("FStockAppQty", count);
                    returnMap.put("FStockQty", count);
                    returnMap.put("FBaseAppQty", count);
                    returnMap.put("FBaseQty", count);
                    fReturnEntry.add(returnMap);
                }
            }
        }

        prdReturnOrderModel.put("FID", fid);
        prdReturnOrderModel.put("FDate", createTime);
        prdReturnOrderModel.put("F_sctld_ZTTLR", createUserName);
        prdReturnOrderModel.put("F_sctld_ZTDJH", billNo);
        prdReturnOrderModel.put("F_sctld_SJLY", source);
        prdReturnOrderModel.put("F_sctld_ZTTLSJ ", createTime);
        prdReturnOrderModel.put("FEntity", fReturnEntry);

        prdReturnOrderParam.put("NeedUpDateFields", new ArrayList<>());
        prdReturnOrderParam.put("NeedReturnFields", new ArrayList<>());
        prdReturnOrderParam.put("IsDeleteEntry", true);
        prdReturnOrderParam.put("SubSystemId", "");
        prdReturnOrderParam.put("IsVerifyBaseDataField", false);
        prdReturnOrderParam.put("IsEntryBatchFill", true);
        prdReturnOrderParam.put("ValidateFlag", true);
        prdReturnOrderParam.put("NumberSearch", true);
        prdReturnOrderParam.put("InterationFlags", "");
        prdReturnOrderParam.put("Model", prdReturnOrderModel);

        param.append("PRD_ReturnMtrl", prdReturnOrderParam);
        List<VtuzxMap> prdReturnBillList = kingdeeService.save(client, "PRD_ReturnMtrl", prdReturnOrderParam);
        VtuzxMap prdReturnMap = prdReturnBillList.get(0);
        String number = VtuzxUtil.getString(prdReturnMap, "Number");
        kingdeeService.submit(client, "PRD_ReturnMtrl", "0", number);
        kingdeeService.audit(client, "PRD_ReturnMtrl", "0", number, "STK_InvCheckResult");
        historyDoc.append("kingdeeNumber", number);
        historyDoc.append("prdReturnOrder", true);

    }


    @Override
    public void syncSaleOut(ObjectId userId, String name, String billNo, String source) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        Document saleOutOrderDoc = saleOutDao.findOne(Criteria.where("billNo").is(billNo));
        int boxCount = VtuzxUtil.getInt(saleOutOrderDoc, "boxCount");
        if (boxCount == 0) {
            historyDoc.append("saleOutOrder", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }
        historyDoc.append("billNo", billNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", saleOutOrderDoc);
        historyDoc.append("event", "saleOut");

        try {
            syncSaleOutInner(historyDoc);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("saleOutOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    private void syncSaleOutInner(Document historyDoc) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        Document data = VtuzxUtil.getObject(historyDoc, "data");
        String createTime = VtuzxUtil.formatYmdF(VtuzxUtil.getObject(data, "createTime"));
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");

        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        List<String> materialNoList = new ArrayList<>();
        List<Document> saleOutOrderList = new ArrayList<>();
        Iterator<Document> saleOutOrderItr = saleOutDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (saleOutOrderItr.hasNext()) {
            Document saleOutOrderDoc = saleOutOrderItr.next();
            String materialNo = VtuzxUtil.getString(saleOutOrderDoc, "materialNo");
            materialNoList.add(materialNo);
            saleOutOrderList.add(saleOutOrderDoc);
        }

        VtuzxMap materialMap = new VtuzxMap();
        String materialNoCond = StringUtils.collectionToDelimitedString(materialNoList, ",", "'", "'");
        List<VtuzxMap> materialQuery = kingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
                        "FTaxRateId.FTaxRate",
                        "FNumber"
                ),
                String.format("FNumber in (%s)", materialNoCond), null, 0, 1);
        if (VtuzxUtil.isEmpty(materialQuery)) return;

        for (VtuzxMap material : materialQuery) {
            double taxRate = VtuzxUtil.getDouble(material, "FTaxRateId.FTaxRate");
            String materialNo = VtuzxUtil.getString(material, "FNumber");
            materialMap.append(materialNo, taxRate);
        }

        List<VtuzxMap> inventoryQuery = kingdeeService.query(client, "STK_Inventory", new VtuzxArrayList<>(
                        "FLot.FNumber",
                        "FMaterialId.FNumber",
                        "FStockId.FNumber",
                        "FBaseQty"
                ),
                String.format("FMaterialId.FNumber in (%s) and FBaseQty != 0", materialNoCond), null, 0, 0);


        //金蝶即时库存如果查到匹配的物料
        List<Document> depDocList = new ArrayList<>();
        for (Map<String, Object> saleOutOrder : saleOutOrderList) {
            boolean no = false;
            String materialNo = VtuzxUtil.getString(saleOutOrder, "materialNo");
            String batchNo = VtuzxUtil.getString(saleOutOrder, "batchNo");
            String stockNo = VtuzxUtil.getString(saleOutOrder, "stockNo");
            double count = VtuzxUtil.getDouble(saleOutOrder, "count");
            for (VtuzxMap inventory : inventoryQuery) {
                String fMaterialId_FNumber = VtuzxUtil.getString(inventory, "FMaterialId.FNumber");
                String fLot_FNumber = VtuzxUtil.getString(inventory, "FLot.FNumber");
                String fStockId_FNumber = VtuzxUtil.getString(inventory, "FStockId.FNumber");
                double qty = VtuzxUtil.getDouble(inventory, "FBaseQty");
                if (materialNo.equals(fMaterialId_FNumber) && batchNo.equals(fLot_FNumber) && stockNo.equals(fStockId_FNumber)) {
                    no = true;
                    if (qty < count) {
                        Document document = new Document("materialNo", materialNo)
                                .append("batchNo", batchNo)
                                .append("stockNo", stockNo)
                                .append("count", count - qty);
                        depDocList.add(document);
                    }
                }
            }
            if (!no) {
                depDocList.add(new Document("materialNo", materialNo)
                        .append("batchNo", batchNo)
                        .append("stockNo", stockNo)
                        .append("count", count));
            }
        }
        if (depDocList.size() != 0) {
            otherInInner(client, depDocList, null, billNo, param);
        }


        Map<String, Object> saleOutOrderParam = new LinkedHashMap<>();
        Map<String, Object> saleOutOrderModel = new LinkedHashMap<>();
        List<Map<String, Object>> fSaleOutEntry = new ArrayList<>();
        Map<String, Object> saleOutMap = new LinkedHashMap<>();
        for (Document saleOut : saleOutOrderList) {
            String materialNo = VtuzxUtil.getString(saleOut, "materialNo");
            double taxRate = VtuzxUtil.getDouble(materialMap, materialNo);
            String stockNo = VtuzxUtil.getString(saleOut, "stockNo");
            String unit = VtuzxUtil.getString(saleOut, "unit");
            String batchNo = VtuzxUtil.getString(saleOut, "batchNo");
            double count = VtuzxUtil.getDouble(saleOut, "count");
            saleOutMap.put("FRowType", "Standard");
            saleOutMap.put("FMaterialID", new VtuzxMap("FNumber", materialNo));
            saleOutMap.put("FUnitID", new VtuzxMap("FNumber", unit));
            saleOutMap.put("FLot", new VtuzxMap("FNumber", batchNo));
            saleOutMap.put("FRealQty", count);
            saleOutMap.put("FIsFree", false);
            saleOutMap.put("FOwnerTypeID", "BD_OwnerOrg");
            saleOutMap.put("FOwnerID", new VtuzxMap("FNumber", "100"));
            saleOutMap.put("FEntryTaxRate", taxRate);
            saleOutMap.put("FStockID", new VtuzxMap("FNumber", stockNo));
            saleOutMap.put("FStockStatusID", new VtuzxMap("FNumber", "KCZT01_SYS"));
            saleOutMap.put("FSalUnitID", new VtuzxMap("FNumber", unit));
            saleOutMap.put("FSALUNITQTY", count);
            saleOutMap.put("FSALBASEQTY", count);
            saleOutMap.put("FPRICEBASEQTY", count);
            saleOutMap.put("FOUTCONTROL", false);
            saleOutMap.put("FIsOverLegalOrg", false);
            saleOutMap.put("FARNOTJOINQTY", count);
            saleOutMap.put("FCheckDelivery", false);
            fSaleOutEntry.add(saleOutMap);
        }

        saleOutOrderModel.put("FBillTypeID", new VtuzxMap("FNUMBER", "XSCKD01_SYS"));
        saleOutOrderModel.put("FDate", createTime);
        saleOutOrderModel.put("FSaleOrgId", new VtuzxMap("FNumber", "100"));
        saleOutOrderModel.put("FCustomerID", new VtuzxMap("FNumber", "01.00001"));
        saleOutOrderModel.put("FStockOrgId", new VtuzxMap("FNumber", "100"));
        saleOutOrderModel.put("FReceiverID", new VtuzxMap("FNumber", "01.00001"));
        saleOutOrderModel.put("FSettleID", new VtuzxMap("FNumber", "01.00001"));
        saleOutOrderModel.put("FPayerID", new VtuzxMap("FNumber", "01.00001"));
        saleOutOrderModel.put("FOwnerTypeIdHead", "BD_OwnerOrg");
        saleOutOrderModel.put("FIsTotalServiceOrCost", false);
        saleOutOrderModel.put("FEntity", fSaleOutEntry);

        saleOutOrderParam.put("NeedUpDateFields", new ArrayList<>());
        saleOutOrderParam.put("NeedReturnFields", new ArrayList<>());
        saleOutOrderParam.put("IsDeleteEntry", true);
        saleOutOrderParam.put("SubSystemId", "");
        saleOutOrderParam.put("IsVerifyBaseDataField", false);
        saleOutOrderParam.put("IsEntryBatchFill", true);
        saleOutOrderParam.put("ValidateFlag", true);
        saleOutOrderParam.put("NumberSearch", true);
        saleOutOrderParam.put("InterationFlags", "");
        saleOutOrderParam.put("Model", saleOutOrderModel);
        param.append("SAL_OUTSTOCK", saleOutOrderParam);
        List<VtuzxMap> outStockBillList = kingdeeService.save(client, "SAL_OUTSTOCK", saleOutOrderParam);
        VtuzxMap outStockMap = outStockBillList.get(0);
        String number = VtuzxUtil.getString(outStockMap, "Number");
        kingdeeService.submit(client, "SAL_OUTSTOCK", "0", number);
        kingdeeService.audit(client, "SAL_OUTSTOCK", "0", number, "STK_InvCheckResult");
        historyDoc.append("kingdeeNumber", number);
        historyDoc.append("saleOutOrder", true);
    }


    @Override
    public void syncDesaltingInStock(ObjectId userId, String name, String taskBillNo, String billNo, String source, String desaltingTime, int number) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        Document desaltingInStockOrderDoc = prdInDao.findOne(Criteria.where("billNo").is(billNo));
        int boxCount = VtuzxUtil.getInt(desaltingInStockOrderDoc, "boxCount");
        if (boxCount == 0) {
            historyDoc.append("desaltingInStock", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }
        historyDoc.append("billNo", billNo);
        historyDoc.append("taskBillNo", taskBillNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", desaltingInStockOrderDoc);
        historyDoc.append("event", "desaltingInStock");

        try {
            syncDesaltingInStockInner(historyDoc, desaltingTime, number);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("desaltingInStock", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    @Override
    public void syncDesaltingInStockBn(ObjectId userId, String name, String taskBillNo, String billNo, String source, String desaltingTime, int number) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        Document desaltingInStockOrderDoc = prdInDao.findOne(Criteria.where("billNo").is(billNo));
        int boxCount = VtuzxUtil.getInt(desaltingInStockOrderDoc, "boxCount");
        if (boxCount == 0) {
            historyDoc.append("desaltingInStock", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }
        historyDoc.append("billNo", billNo);
        historyDoc.append("taskBillNo", taskBillNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("type", "product");
        historyDoc.append("data", desaltingInStockOrderDoc);
        historyDoc.append("event", "desaltingInStock");

        try {
            syncDesaltingInStockInnerBn(historyDoc, desaltingTime, number);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("desaltingInStock", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    //变品
    private void syncDesaltingInStockInner(Document historyDoc, String desaltingTime, int outNum) throws Exception {
        String taskBillNo = VtuzxUtil.getString(historyDoc, "taskBillNo");
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");
        Document data = VtuzxUtil.getObject(historyDoc, "data");
        String desCreateTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(data, "createTime"));
        String desAuditTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(data, "auditTime"));
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        //查询变品入库单
        double desCount = 0d;
        String desMaterialNo = "";
        List<Document> desaltingInDetailList = new ArrayList<>();//批次不全是6的变品
        //判断变品批次是否全是6，全是6的话做一个批号调整单
        List<Document> desaltingList = new ArrayList<>();//存批次全是6的数据
        String desStockNo = "";
        Iterator<Document> desaltingInDetailItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (desaltingInDetailItr.hasNext()) {
            Document desaltingInDetailDoc = desaltingInDetailItr.next();
            double count = VtuzxUtil.getDouble(desaltingInDetailDoc, "count");
            desCount += count;
            String batchNo = VtuzxUtil.getString(desaltingInDetailDoc, "batchNo");
            desMaterialNo = VtuzxUtil.getString(desaltingInDetailDoc, "materialNo");
            desStockNo = VtuzxUtil.getString(desaltingInDetailDoc, "stockNo");
            //判断是否全是6
            Pattern pattern = Pattern.compile("-?[6]+\\.?[6]*");
            Matcher isNum = pattern.matcher(batchNo);
            if (isNum.matches() || batchNo.contains("BN66")) {//如果全是的话
                desaltingList.add(desaltingInDetailDoc);
            }
            desaltingInDetailList.add(desaltingInDetailDoc);

        }
        double desCountTwo = desCount;


        //查生产订单
        List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                        "FBillNo",
                        "FQty",
                        "F_scdd_ZTDJH",
                        "FMaterialId.FNumber",
                        "FDate"
                ),
                String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(prdOrderQuery)) return;
        String kingdeeBillNo = VtuzxUtil.getString(prdOrderQuery.get(0), "FBillNo");


        //根据任务单号查询用料清单
        List<VtuzxMap> pickQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                        "FID",
                        "FBillNo",
                        "FMOBillNO",
                        "FMaterialID2.FNumber",
                        "FUnitID2.FNumber",
                        "FNeedQty2",
                        "FEntity_FEntryID"
                ),
                String.format("FMOBillNO = '%s'", kingdeeBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(pickQuery)) return;
        String kingdeePickBillNo = VtuzxUtil.getString(pickQuery.get(0), "FBillNo");


        //用用料清单下推退料单
        List<String> billNoList = new ArrayList<>();
        billNoList.add(kingdeePickBillNo);
        Map<String, Object> pickToReturnMap = new LinkedHashMap<>();
        pickToReturnMap.put("Ids", "");
        pickToReturnMap.put("Numbers", billNoList);
        pickToReturnMap.put("EntryIds", "");
        pickToReturnMap.put("RuleId", "ora_PRD_PPBOM2RETURNMTRL_ZY");//下推规则
        pickToReturnMap.put("TargetBillTypeId", "");
        pickToReturnMap.put("TargetOrgId", 0);
        pickToReturnMap.put("IsEnableDefaultRule", false);
        pickToReturnMap.put("IsDraftWhenSaveFail", true);
        pickToReturnMap.put("CustomParams", new VtuzxMap());
        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        param.append("PRD_MO", pickToReturnMap);

        List<VtuzxMap> prdToReturnStockList = kingdeeService.push(client, "PRD_PPBOM", pickToReturnMap);
        VtuzxMap prdToReturnStocks = prdToReturnStockList.get(0);
        String pickToReturnBillNo = VtuzxUtil.getString(prdToReturnStocks, "Number");
        String pickToReturnId = VtuzxUtil.getString(prdToReturnStocks, "Id");


        //修改退料单
        List<VtuzxMap> returnQuery = kingdeeService.query(client, "PRD_ReturnMtrl", new VtuzxArrayList<>(
                        "FBillNo",
                        "FEntity_FEntryID",
                        "FMaterialId.FNumber",
                        "FLot.FNumber",
                        "FQty"
                ),
                String.format("FID = '%s'", pickToReturnId), null, 0, 0);
        if (VtuzxUtil.isEmpty(returnQuery)) return;

        //计算每条分录的最大退单数从用料清单查询
        VtuzxMap countDataMap = new VtuzxMap();
        //查询用料清单
        List<VtuzxMap> prdBomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                        "FBillNo",
                        "FLot.FNumber",
                        "FMaterialID2.FNumber",
                        "FMaterialName1",
                        "FPickedQty",//已领数量
                        "FRePickedQty",//补领数量
                        "FScrapQty",//报废数量
                        "FGoodReturnQty",//良品退料数量
                        "FSelPrcdReturnQty",//退料选单数量
                        "FConsumeQty"//消耗数量

                ),
                String.format("FMOBillNO = '%s'", kingdeeBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(prdBomQuery)) return;
        for (VtuzxMap prdBomMap : prdBomQuery) {
            String fMaterialNo = VtuzxUtil.getString(prdBomMap, "FMaterialID2.FNumber");
            String batchNo = VtuzxUtil.getString(prdBomMap, "FLot.FNumber");
            BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap, "FPickedQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();
            double FPickedQtyCount = BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap, "FPickedQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();//已领数量
            double FRePickedQtyCount = BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap, "FRePickedQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();//补领数量
            double FScrapQtyCount = BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap, "FScrapQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();//报废数量
//            double FSelPrcdReturnQtyCount = BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap,"FSelPrcdReturnQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();//退料选单数量
            double FGoodReturnQty = BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap, "FGoodReturnQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();//良品退料选单数量
            double FConsumeQtyCount = BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap, "FConsumeQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();//消耗数量
            double count = FPickedQtyCount + FRePickedQtyCount - FScrapQtyCount - FGoodReturnQty - FConsumeQtyCount;
            count = BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue();
            double getCount = VtuzxUtil.getDouble(countDataMap, fMaterialNo + "_" + batchNo);
            if (getCount == 0) {
                countDataMap.put(fMaterialNo + "_" + batchNo, count);
            } else {
                countDataMap.put(fMaterialNo + "_" + batchNo, count + getCount);
            }

        }
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String produceHouseName = VtuzxUtil.getString(prdTaskDoc, "produceHouseName");
        //水袋的变品批次是6的话品项需要是领料或者补料的品,干参的变品不需要跟领料或者补料的一样
        //根据生产车间判断是干参的变品还是水袋的变品
        //按照变品退料单的数量，在退料单中按默认排序减去数量
        List<Map<String, Object>> prdReturnStockList = new ArrayList<>();
        Map<String, Object> prdReturnStockParam = new LinkedHashMap<>();
        Map<String, Object> prdReturnStockModel = new LinkedHashMap<>();
        if ("干参包装车间".equals(produceHouseName)) {
            for (VtuzxMap returnMap : returnQuery) {
                Map<String, Object> prdReturnStockMap = new LinkedHashMap<>();
                String returnEntryId = VtuzxUtil.getString(returnMap, "FEntity_FEntryID");
                String fMaterialNo = VtuzxUtil.getString(returnMap, "FMaterialId.FNumber");
                String batchNo = VtuzxUtil.getString(returnMap, "FLot.FNumber");
                double fQty = VtuzxUtil.getDouble(countDataMap, fMaterialNo + "_" + batchNo);
                double returnQty = VtuzxUtil.getDouble(returnMap, "FQty");
                if (returnQty > 0) {
                    if (desCount >= returnQty) {
                        prdReturnStockMap.put("FEntryID", returnEntryId);
                        prdReturnStockMap.put("FQty", returnQty);
                        prdReturnStockMap.put("FAPPQty", returnQty);
                        prdReturnStockList.add(prdReturnStockMap);
                    } else {
                        prdReturnStockMap.put("FEntryID", returnEntryId);
                        prdReturnStockMap.put("FQty", desCount);
                        prdReturnStockMap.put("FAPPQty", desCount);
                        prdReturnStockList.add(prdReturnStockMap);
                    }
                    desCount -= returnQty;
                    if (desCount <= 0) break;

                }
            }
        } else { //水袋的变品
            for (VtuzxMap returnMap : returnQuery) {
                Map<String, Object> prdReturnStockMap = new LinkedHashMap<>();
                String returnEntryId = VtuzxUtil.getString(returnMap, "FEntity_FEntryID");
                String fMaterialNo = VtuzxUtil.getString(returnMap, "FMaterialId.FNumber");
                String batchNo = VtuzxUtil.getString(returnMap, "FLot.FNumber");
                double fQty = VtuzxUtil.getDouble(countDataMap, fMaterialNo + "_" + batchNo);
                double returnQty = VtuzxUtil.getDouble(returnMap, "FQty");
                if (fMaterialNo.equals(desMaterialNo)) {
                    if (returnQty > 0) {
                        if (desCount >= returnQty) {
                            prdReturnStockMap.put("FEntryID", returnEntryId);
                            prdReturnStockMap.put("FQty", returnQty);
                            prdReturnStockMap.put("FAPPQty", returnQty);
                            prdReturnStockMap.put("FStockId", new VtuzxMap("FNumber", desStockNo));
                            prdReturnStockList.add(prdReturnStockMap);
                        } else {
                            prdReturnStockMap.put("FEntryID", returnEntryId);
                            prdReturnStockMap.put("FQty", desCount);
                            prdReturnStockMap.put("FAPPQty", desCount);
                            prdReturnStockMap.put("FStockId", new VtuzxMap("FNumber", desStockNo));
                            prdReturnStockList.add(prdReturnStockMap);
                        }
                        desCount -= returnQty;
                        if (desCount <= 0) break;

                    }
                }
            }
        }

        prdReturnStockModel.put("FID", pickToReturnId);
        prdReturnStockModel.put("FDate", desCreateTime);//修改日期
        prdReturnStockModel.put("FEntity", prdReturnStockList);

        prdReturnStockParam.put("NeedUpDateFields", new ArrayList<>());
        prdReturnStockParam.put("NeedReturnFields", new ArrayList<>());
        prdReturnStockParam.put("IsDeleteEntry", true);
        prdReturnStockParam.put("SubSystemId", "");
        prdReturnStockParam.put("IsVerifyBaseDataField", false);
        prdReturnStockParam.put("IsEntryBatchFill", true);
        prdReturnStockParam.put("ValidateFlag", true);
        prdReturnStockParam.put("NumberSearch", true);
        prdReturnStockParam.put("InterationFlags", "");
        prdReturnStockParam.put("Model", prdReturnStockModel);
        param.append("PRD_ReturnMtrl", prdReturnStockParam);
        String returnBillNumber = "";//变品退料单号
        try {
            List<VtuzxMap> inStockList = kingdeeService.save(client, "PRD_ReturnMtrl", prdReturnStockParam);
            VtuzxMap inStock = inStockList.get(0);
            returnBillNumber = VtuzxUtil.getString(inStock, "Number");
            kingdeeService.submit(client, "PRD_ReturnMtrl", "0", returnBillNumber);
            kingdeeService.audit(client, "PRD_ReturnMtrl", "0", returnBillNumber, "STK_InvCheckResult");
        } catch (Exception e) {
            _logger.info(e.getMessage());
        }

        //变品数量做生产订单
        Document taskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String produceHouseNo = VtuzxUtil.getString(taskDoc, "produceHouseNo");
        String createUserName = VtuzxUtil.getString(taskDoc, "createUserName");
        String auditUserName = VtuzxUtil.getString(taskDoc, "auditUserName");

        //查询金蝶部门
        List<VtuzxMap> departmentQuery = kingdeeService.query(client, "BD_Department", new VtuzxArrayList<>(
                        "FNumber1",
                        "FNumber"
                ),
                String.format("FNumber1 = '%s'", produceHouseNo), null, 0, 1);
        if (VtuzxUtil.isEmpty(departmentQuery)) {
            throw new VtuzxException(String.format("部门[%s]在金蝶中不存在", produceHouseNo));
        }
        String department = VtuzxUtil.getString(departmentQuery.get(0), "FNumber");


        List<String> desKingdeeBillNoList = new ArrayList<>();
        //如果有全是6批次的做批次调整，否则正常走变品
        if (!VtuzxUtil.isEmpty(desaltingList)) {
            //批次调整
            syncBatchAndExp(desaltingList, taskBillNo, returnBillNumber);
        } else {
            //变品
            for (Document desaltingInDetail : desaltingInDetailList) { //按物料区分做订单
                List<Map<String, Object>> fOutStockEntry = new ArrayList<>();
                VtuzxMap prdOrderParam = new VtuzxMap();
                Map<String, Object> prdOrderModel = new LinkedHashMap<>();
                String materialNo = VtuzxUtil.getString(desaltingInDetail, "materialNo");
                Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
                if (VtuzxUtil.isEmpty(materialDoc)) {
                    throw new VtuzxException(String.format("编码为[%s]的物料不存在", materialNo));
                }
                String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
                double count = Math.abs(VtuzxUtil.getDouble(desaltingInDetail, "count"));
                Map<String, Object> detailMap = new LinkedHashMap<>();
                detailMap.put("FProductType", "1");
                detailMap.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
                detailMap.put("FWorkShopID", new VtuzxMap("FNumber", department));
                detailMap.put("FUnitId", new VtuzxMap("FNumber", unit));
                detailMap.put("FQty", count);
                detailMap.put("FYieldQty", count);
                detailMap.put("FPlanStartDate", desCreateTime);//计划开工日期
                detailMap.put("FPlanFinishDate", desAuditTime);
                detailMap.put("FRequestOrgId", new VtuzxMap("FNumber", "100"));
                detailMap.put("FISBACKFLUSH", true);
                detailMap.put("FStockInOrgId", new VtuzxMap("FNumber", "100"));
                detailMap.put("FBaseYieldQty", count);
                detailMap.put("FInStockOwnerTypeId", "BD_OwnerOrg");
                detailMap.put("FBaseStockInLimitH", count);
                detailMap.put("FInStockOwnerId", new VtuzxMap("FNumber", "100"));
                detailMap.put("FCheckProduct", false);
                detailMap.put("FBaseStockInLimitL", count);
                detailMap.put("FBaseUnitQty", count);
                detailMap.put("FBaseUnitId", new VtuzxMap("FNumber", unit));
                detailMap.put("FStockInLimitH", count);
                detailMap.put("FStockInLimitL", count);
                detailMap.put("FCostRate", 100.0);
                detailMap.put("FCreateType", "1");
                detailMap.put("FYieldRate", 100.0);
                detailMap.put("FGroup", "1");
                detailMap.put("FNoStockInQty", count);
                detailMap.put("FBaseNoStockInQty", count);
                detailMap.put("FRowId", "ba36ddd9-bb80-80b7-11ed-4f73ea562f1d");
                detailMap.put("FScheduleStatus", "1");
                detailMap.put("FPickMtrlStatus", "1");
                detailMap.put("FMOChangeFlag", false);
                detailMap.put("FIsFirstInspect", false);
                detailMap.put("FFirstInspectStatus", "A");
                /*detailMap.put("FSTOCKID", new VtuzxMap("FNumber", "001"));*/
                //20251014生产成品“委外库”
                detailMap.put("FSTOCKID", new VtuzxMap("FNumber", "002"));
                fOutStockEntry.add(detailMap);

                prdOrderModel.put("FID", 0);
                prdOrderModel.put("FBillType", new VtuzxMap("FNumber", "SCDD03_SYS"));
                prdOrderModel.put("FDate", desCreateTime);
                prdOrderModel.put("FPrdOrgId", new VtuzxMap("FNumber", "100"));
                prdOrderModel.put("FWorkShopID0", new VtuzxMap("FNumber", department));
                prdOrderModel.put("FOwnerTypeId", "BD_OwnerOrg");
                prdOrderModel.put("FIsRework", false);
                prdOrderModel.put("FBusinessType", "1");
                prdOrderModel.put("FTrustteed", false);
                prdOrderModel.put("FIsEntrust", false);
                prdOrderModel.put("FPPBOMType", "1");
                prdOrderModel.put("FIssueMtrl", false);
                prdOrderModel.put("F_scdd_ZTSQR", createUserName);
                prdOrderModel.put("F_scdd_ZTSQSJ", desCreateTime);
                prdOrderModel.put("F_scdd_ZTSHR", auditUserName);
                prdOrderModel.put("F_scdd_ZTDJH", taskBillNo);
                prdOrderModel.put("F_scdd_SJLY", source);
                prdOrderModel.put("F_scdd_ZTSHSJ", desCreateTime);
                prdOrderModel.put("FTreeEntity", fOutStockEntry);

                prdOrderParam.append("Model", prdOrderModel);
                historyDoc.append("param", new VtuzxMap("PRD_MO", prdOrderParam));
                List<VtuzxMap> stkOutStockList = kingdeeService.save(client, "PRD_MO", prdOrderParam);
                VtuzxMap stkOutStockMap = stkOutStockList.get(0);
                String number = VtuzxUtil.getString(stkOutStockMap, "Number");
                kingdeeService.submit(client, "PRD_MO", "0", number);
                kingdeeService.audit(client, "PRD_MO", "0", number, "STK_InvCheckResult");
                desKingdeeBillNoList.add(number);
            }


            //查询退料单 按照退料单修改用料清单
            List<VtuzxMap> returnMaterialOrderQuery = kingdeeService.query(client, "PRD_ReturnMtrl", new VtuzxArrayList<>(
                            "FBillNo",
                            "FEntity_FEntryID",
                            "FMaterialId.FNumber",
                            "FStockId.FNumber",
                            "FQty",
                            "FUnitID.FNumber",
                            "FLot.FNumber"
                    ),
                    String.format("FID = '%s'", pickToReturnId), null, 0, 0);
            if (VtuzxUtil.isEmpty(returnMaterialOrderQuery)) return;

            int desNo = 0; //记录这是第几个订单
            for (String desKingdeeBillNo : desKingdeeBillNoList) {
                desNo++;
                List<Map<String, Object>> fMaterialBomEntry = new ArrayList<>();
                //根据生产订单单号找到对应用料清单
                List<VtuzxMap> materialBomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                                "FID",
                                "FBillNo",
                                "FMOBillNO",
                                "FMaterialID2.FNumber",
                                "FUnitID2.FNumber",
                                "FNeedQty2",
                                "FEntity_FEntryID"
                        ),
                        String.format("FMOBillNO = '%s'", desKingdeeBillNo), null, 0, 0);
                if (VtuzxUtil.isEmpty(materialBomQuery)) return;
                String fid = VtuzxUtil.getString(materialBomQuery.get(0), "FID");
                String entryId = VtuzxUtil.getString(materialBomQuery.get(0), "FEntity_FEntryID");

                //留一个原单据的分录
                materialPickInner(materialBomQuery.get(0), fMaterialBomEntry);
                for (VtuzxMap returnMaterialOrder : returnMaterialOrderQuery) {
                    String materialNo = VtuzxUtil.getString(returnMaterialOrder, "FMaterialId.FNumber");
                    String unit = VtuzxUtil.getString(returnMaterialOrder, "FUnitID.FNumber");
                    String batchNo = VtuzxUtil.getString(returnMaterialOrder, "FLot.FNumber");
                    String stockNo = VtuzxUtil.getString(returnMaterialOrder, "FStockId.FNumber");
                    double fQty = VtuzxUtil.getDouble(returnMaterialOrder, "FQty");
                    double lineCount;
                    if (desNo == desKingdeeBillNoList.size()) { // 如果是最后一行
                        lineCount = fQty - (BigDecimal.valueOf(fQty / returnMaterialOrderQuery.size()).setScale(2, RoundingMode.HALF_UP).doubleValue() * (desNo - 1));
                    } else {
                        lineCount = BigDecimal.valueOf(fQty / returnMaterialOrderQuery.size()).setScale(2, RoundingMode.HALF_UP).doubleValue();
                    }
                    Map<String, Object> materialBoms = new LinkedHashMap<>();
                    materialBoms.put("FMaterialID2", new VtuzxMap("FNumber", materialNo));
                    materialBoms.put("FMaterialType", "1");
                    materialBoms.put("FSupplyType", "");
                    materialBoms.put("FDosageType", "2");
                    materialBoms.put("FNumerator", 1);//分子
                    materialBoms.put("FDenominator", 1);//分母
                    materialBoms.put("FUnitID2", new VtuzxMap("FNumber", unit));
                    materialBoms.put("FFixScrapQty", 0);
                    materialBoms.put("FScrapRate", 0);
                    materialBoms.put("FNeedDate2", "2022-10-10");
                    materialBoms.put("FStdQty", lineCount);
                    materialBoms.put("FNeedQty2 ", lineCount);
                    materialBoms.put("FMustQty", lineCount);
                    materialBoms.put("FSupplyOrg", new VtuzxMap("FNumber", "100"));
                    materialBoms.put("FIsKeyComponent", false);
                    materialBoms.put("FBomId2", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FAllowOver", false);
                    materialBoms.put("FWorkCalId2", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FBaseNumerator", 1);
                    materialBoms.put("FReserveType", "");
                    materialBoms.put("FBASEDENOMINATOR", 1);
                    materialBoms.put("FSMEntryId", 0);
                    materialBoms.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                    materialBoms.put("FEntrustPickOrgId", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FOperID", 0);
                    materialBoms.put("FLot", new VtuzxMap("FNumber", batchNo));
                    materialBoms.put("FStockId", new VtuzxMap("FNumber", stockNo)); //取第一次领料的单据
                    materialBoms.put("FOffsetTime", 0);
                    materialBoms.put("FProcessID", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FIssueType", "1");
                    materialBoms.put("FSrcTransOrgId", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FSrcTransStockId", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FNoPickedQty", 0);
                    materialBoms.put("FInventoryQty", 0);
                    materialBoms.put("FIsSkip", false);
                    materialBoms.put("FISMinIssueQty", false);
                    materialBoms.put("FIsGetScrap", false);
                    materialBoms.put("FPPBomEntryType", "0");
                    materialBoms.put("FUPDATERID", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FUPDateDate", "2022-10-10");
                    materialBoms.put("FOwnerTypeId", "BD_OwnerOrg");
                    materialBoms.put("FSupplyMode", "z");
                    materialBoms.put("FBaseNoPickedQty", 0);
                    materialBoms.put("FIsMrpRun", false);
                    materialBoms.put("FSrcPPBOMID", 0);
                    materialBoms.put("FSrcPPBOMEntryId", 0);
                    materialBoms.put("FStockReadyQty", 0);
                    materialBoms.put("FBaseStockReadyQty", 0);
                    materialBoms.put("FBaseUnitID1", new VtuzxMap("FNumber", unit));
                    materialBoms.put("FReturnNoOkQty", 0);
                    materialBoms.put("FMoType1", new VtuzxMap("FNumber", "SCDD03_SYS"));
                    materialBoms.put("FOwnerID", new VtuzxMap("FNumber", "100"));
                    materialBoms.put("FGroupByOwnerId", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FIsExpand", false);
                    materialBoms.put("FCheckReturnMtrl", false);
                    materialBoms.put("FBaseReturnAppSelQty", 0);
                    materialBoms.put("FReturnAppSelQty", 0);
                    fMaterialBomEntry.add(materialBoms);
                }

                Map<String, Object> prdPickOrderParam = new LinkedHashMap<>();
                Map<String, Object> prdPickOrderModel = new LinkedHashMap<>();
                prdPickOrderModel.put("FID", fid);
                prdPickOrderModel.put("FEntity", fMaterialBomEntry);

                prdPickOrderParam.put("NeedUpDateFields", new ArrayList<>());
                prdPickOrderParam.put("NeedReturnFields", new ArrayList<>());
                prdPickOrderParam.put("IsDeleteEntry", true);
                prdPickOrderParam.put("SubSystemId", "");
                prdPickOrderParam.put("IsVerifyBaseDataField", true);
                prdPickOrderParam.put("IsEntryBatchFill", false);
                prdPickOrderParam.put("ValidateFlag", true);
                prdPickOrderParam.put("NumberSearch", true);
                prdPickOrderParam.put("InterationFlags", "");
                prdPickOrderParam.put("Model", prdPickOrderModel);
                param.append("PRD_PPBOM", prdPickOrderParam);
                kingdeeService.save(client, "PRD_PPBOM", prdPickOrderParam);

                //查新增后的分录id
                List<VtuzxMap> materialBomTwoQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                                "FID",
                                "FBillNo",
                                "FMOBillNO",
                                "FMaterialID2.FNumber",
                                "FUnitID2.FNumber",
                                "FNeedQty2",
                                "FEntity_FEntryID"
                        ),
                        String.format("FMOBillNO = '%s'", desKingdeeBillNo), null, 0, 0);

                if (VtuzxUtil.isEmpty(materialBomTwoQuery)) return;

                List<Map<String, Object>> entryIdList = new ArrayList<>();
                for (VtuzxMap materialBomTwo : materialBomTwoQuery) {
                    Map<String, Object> map = new LinkedHashMap<>();
                    String fEntryID = VtuzxUtil.getString(materialBomTwo, "FEntity_FEntryID");
                    if (!fEntryID.equals(entryId)) {
                        map.put("FEntryID", fEntryID);
                        entryIdList.add(map);
                    }
                }

                Map<String, Object> prdPickOrderTwoParam = new LinkedHashMap<>();
                Map<String, Object> prdPickOrderTwoModel = new LinkedHashMap<>();

                prdPickOrderTwoModel.put("FID", fid);
                prdPickOrderTwoModel.put("FEntity", entryIdList);

                prdPickOrderTwoParam.put("NeedUpDateFields", new ArrayList<>());
                prdPickOrderTwoParam.put("NeedReturnFields", new ArrayList<>());
                prdPickOrderTwoParam.put("IsDeleteEntry", true);
                prdPickOrderTwoParam.put("SubSystemId", "");
                prdPickOrderTwoParam.put("IsVerifyBaseDataField", true);
                prdPickOrderTwoParam.put("IsEntryBatchFill", false);
                prdPickOrderTwoParam.put("ValidateFlag", true);
                prdPickOrderTwoParam.put("NumberSearch", true);
                prdPickOrderTwoParam.put("InterationFlags", "");
                prdPickOrderTwoParam.put("Model", prdPickOrderTwoModel);
                param.append("PRD_PPBOM", prdPickOrderTwoParam);
                List<VtuzxMap> prdPPBomsList = kingdeeService.save(client, "PRD_PPBOM", prdPickOrderTwoParam);
                VtuzxMap prdPPBomsMap = prdPPBomsList.get(0);
                String bomNumber = VtuzxUtil.getString(prdPPBomsMap, "Number");
                kingdeeService.submit(client, "PRD_PPBOM", "0", bomNumber);
                kingdeeService.audit(client, "PRD_PPBOM", "0", bomNumber, "STK_InvCheckResult");

                //生产订单执行至开工
                kingdeeService.toRelease(client, "PRD_MO", "ToStart", "0", desKingdeeBillNo);
                //修改生产订单下达时间
                try {
                    kingdeeService.orderUpdate(client, "PRD_MO", desKingdeeBillNo, desCreateTime);
                } catch (Exception e) {
                    _logger.info(e.getMessage());
                }
                //TODO
                //用料清单下推生产领料
                List<String> bomNumberList = new ArrayList<>();
                bomNumberList.add(bomNumber);
                Map<String, Object> bomToPickMap = new LinkedHashMap<>();
                bomToPickMap.put("Ids", "");
                bomToPickMap.put("Numbers", bomNumberList);
                bomToPickMap.put("EntryIds", "");
                bomToPickMap.put("RuleId", "Org_YBLL");
                bomToPickMap.put("TargetBillTypeId", "");
                bomToPickMap.put("TargetOrgId", 0);
                bomToPickMap.put("IsEnableDefaultRule", false);
                bomToPickMap.put("IsDraftWhenSaveFail", false);
                bomToPickMap.put("CustomParams", new VtuzxMap());
                param.append("PRD_PPBOM", bomToPickMap);
                List<VtuzxMap> pickBillList = kingdeeService.push(client, "PRD_PPBOM", bomToPickMap);
                VtuzxMap pickBillMap = pickBillList.get(0);
                String desPickBillNo = VtuzxUtil.getString(pickBillMap, "Number");
                String id = VtuzxUtil.getString(pickBillMap, "Id");

                Map<String, Object> updatePickParam = new LinkedHashMap<>();
                Map<String, Object> updatePickModel = new LinkedHashMap<>();

                updatePickModel.put("FID", id);
                updatePickModel.put("Fdate", desCreateTime);
                updatePickModel.put("F_sclld_ZTLLR", createUserName);
                updatePickModel.put("F_sclld_ZTDJH", billNo);
                updatePickModel.put("F_sclld_SJLY", source);
                updatePickModel.put("F_sclld_ZTLLSJ", desCreateTime);

                updatePickParam.put("NeedUpDateFields", new ArrayList<>());
                updatePickParam.put("NeedReturnFields", new ArrayList<>());
                updatePickParam.put("IsDeleteEntry", true);
                updatePickParam.put("SubSystemId", "");
                updatePickParam.put("IsVerifyBaseDataField", true);
                updatePickParam.put("IsEntryBatchFill", false);
                updatePickParam.put("ValidateFlag", true);
                updatePickParam.put("NumberSearch", true);
                updatePickParam.put("InterationFlags", "");
                updatePickParam.put("Model", updatePickModel);

                param.append("PRD_PickMtrl", updatePickParam);
                try {
                    kingdeeService.save(client, "PRD_PickMtrl", updatePickParam);
                    kingdeeService.submit(client, "PRD_PickMtrl", "0", desPickBillNo);
                    kingdeeService.audit(client, "PRD_PickMtrl", "0", desPickBillNo, "STK_InvCheckResult");

                } catch (Exception e) {
                    _logger.info(e.getMessage());
                }


                //生产订单下推入库
                List<String> prdBillNoList = new ArrayList<>();
                prdBillNoList.add(desKingdeeBillNo);
                Map<String, Object> prdToInStockMap = new LinkedHashMap<>();
                prdToInStockMap.put("Ids", "");
                prdToInStockMap.put("Numbers", prdBillNoList);
                prdToInStockMap.put("EntryIds", "");
                prdToInStockMap.put("RuleId", "ora_midPRD_PROINSTOCK");
                prdToInStockMap.put("TargetBillTypeId", "");
                prdToInStockMap.put("TargetOrgId", 0);
                prdToInStockMap.put("IsEnableDefaultRule", false);
                prdToInStockMap.put("IsDraftWhenSaveFail", false);
                prdToInStockMap.put("CustomParams", new VtuzxMap());

                List<VtuzxMap> prdToInStockList = kingdeeService.push(client, "PRD_MO", prdToInStockMap);
                VtuzxMap prdToInStocks = prdToInStockList.get(0);
                String prdToInStockBillNo = VtuzxUtil.getString(prdToInStocks, "Number");

                //查询生产入库
                List<VtuzxMap> inStockQuery = kingdeeService.query(client, "PRD_INSTOCK", new VtuzxArrayList<>(
                                "FID",
                                "FBillNo",
                                "FEntity_FEntryID",
                                "FMaterialId.FNumber",
                                "FRealQty"
                        ),
                        String.format("FBillNo = '%s'", prdToInStockBillNo), null, 0, 1);
                if (VtuzxUtil.isEmpty(inStockQuery)) return;
                VtuzxMap inStockMap = inStockQuery.get(0);
                String inStockId = VtuzxUtil.getString(inStockMap, "FID");


                List<Map<String, Object>> prdInStockList = new ArrayList<>();
                Map<String, Object> prdInStockParam = new LinkedHashMap<>();
                Map<String, Object> prdInStockModel = new LinkedHashMap<>();
                //修改入库
                for (VtuzxMap inMap : inStockQuery) {
                    String inStockEntryId = VtuzxUtil.getString(inMap, "FEntity_FEntryID");
                    String inMaterialNo = VtuzxUtil.getString(inMap, "FMaterialId.FNumber");
                    for (Document desaltingInDetail : desaltingInDetailList) {
                        String materialNo = VtuzxUtil.getString(desaltingInDetail, "materialNo");
                        String batchNo = VtuzxUtil.getString(desaltingInDetail, "batchNo");
                        String stockNo = VtuzxUtil.getString(desaltingInDetail, "stockNo");
                        Map<String, Object> entryMap = new LinkedHashMap<>();
                        if (inMaterialNo.equals(materialNo)) {
                            entryMap.put("FEntryID", inStockEntryId);
                            entryMap.put("fStockId", new VtuzxMap("FNumber", stockNo));
                            entryMap.put("FLot", new VtuzxMap("FNumber", batchNo));
                            prdInStockList.add(entryMap);
                        }
                    }
                }

                prdInStockModel.put("FID", inStockId);
                prdInStockModel.put("FDate", desCreateTime);
                prdInStockModel.put("F_scrkd_ZTRKR", createUserName);
                prdInStockModel.put("F_scrkd_ZTRKSJ", desCreateTime);
                prdInStockModel.put("F_scrkd_ZTDJH", billNo);
                prdInStockModel.put("F_scrkd_SJLY", source);
                prdInStockModel.put("FEntity", prdInStockList);

                prdInStockParam.put("NeedUpDateFields", new ArrayList<>());
                prdInStockParam.put("NeedReturnFields", new ArrayList<>());
                prdInStockParam.put("IsDeleteEntry", false);
                prdInStockParam.put("SubSystemId", "");
                prdInStockParam.put("IsVerifyBaseDataField", false);
                prdInStockParam.put("IsEntryBatchFill", true);
                prdInStockParam.put("ValidateFlag", true);
                prdInStockParam.put("NumberSearch", true);
                prdInStockParam.put("InterationFlags", "");
                prdInStockParam.put("Model", prdInStockModel);

                param.append("PRD_INSTOCK", prdInStockParam);
                List<VtuzxMap> prdInList = kingdeeService.save(client, "PRD_INSTOCK", prdInStockParam);
                VtuzxMap prdInMap = prdInList.get(0);
                String inNumber = VtuzxUtil.getString(prdInMap, "Number");
                kingdeeService.submit(client, "PRD_INSTOCK", "0", inNumber);
                kingdeeService.audit(client, "PRD_INSTOCK", "0", inNumber, "STK_InvCheckResult");
            }
        }

    }

    //新工厂变品
    private void syncDesaltingInStockInnerBn(Document historyDoc, String desaltingTime, int outNum) throws Exception {
        String taskBillNo = VtuzxUtil.getString(historyDoc, "taskBillNo");
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");
        Document data = VtuzxUtil.getObject(historyDoc, "data");
        String type = VtuzxUtil.getString(historyDoc, "type");
        String desCreateTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(data, "createTime"));
        String desAuditTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(data, "auditTime"));
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdeeYX();
        //查询变品入库单
        double desCount = 0d;
        String desMaterialNo = "";
        List<Document> desaltingInDetailList = new ArrayList<>();//批次不全是6的变品

        List<Document> desaltingList = new ArrayList<>();//存批次全是6的数据
        String desStockNo = "";
        //取出明细中批次是BN的
        Iterator<Document> desaltingInDetailItr = prdInDetailDao
                .findList(Criteria.where("billNo").is(billNo).and("batchNo").regex("BN"), null, 0, 0);
        while (desaltingInDetailItr.hasNext()) {
            Document desaltingInDetailDoc = desaltingInDetailItr.next();
            double count = VtuzxUtil.getDouble(desaltingInDetailDoc, "count");
            desCount += count;
            desMaterialNo = VtuzxUtil.getString(desaltingInDetailDoc, "materialNo");
            desStockNo = VtuzxUtil.getString(desaltingInDetailDoc, "stockNo");
            desaltingInDetailList.add(desaltingInDetailDoc);
            String batchNo = VtuzxUtil.getString(desaltingInDetailDoc, "batchNo");
            if(batchNo.equals("BN66666666")){
                desaltingList.add(desaltingInDetailDoc);
            }
        }
        //查生产订单
        List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                        "FBillNo",
                        "FQty",
                        "F_scdd_ZTDJH",
                        "FMaterialId.FNumber",
                        "FDate"
                ),
                String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(prdOrderQuery)) return;
        String kingdeeBillNo = VtuzxUtil.getString(prdOrderQuery.get(0), "FBillNo");


        //根据任务单号查询用料清单
        List<VtuzxMap> pickQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                        "FID",
                        "FBillNo",
                        "FMOBillNO",
                        "FMaterialID2.FNumber",
                        "FUnitID2.FNumber",
                        "FNeedQty2",
                        "FEntity_FEntryID"
                ),
                String.format("FMOBillNO = '%s'", kingdeeBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(pickQuery)) return;
        String kingdeePickBillNo = VtuzxUtil.getString(pickQuery.get(0), "FBillNo");


        //用用料清单下推退料单
        List<String> billNoList = new ArrayList<>();
        billNoList.add(kingdeePickBillNo);
        Map<String, Object> pickToReturnMap = new LinkedHashMap<>();
        pickToReturnMap.put("Ids", "");
        pickToReturnMap.put("Numbers", billNoList);
        pickToReturnMap.put("EntryIds", "");
        pickToReturnMap.put("RuleId", VtuzxUtil.getString(prdPushRuleDao.findOne(Criteria
                .where("ruleName").is("PPBOMPushReturnMtrl")
                .and("ruleType").is("desalting")
                .and("tokenType").is("kingdee3")
        ), "ruleId"));
        pickToReturnMap.put("TargetBillTypeId", "");
        pickToReturnMap.put("TargetOrgId", 0);
        pickToReturnMap.put("IsEnableDefaultRule", false);
        pickToReturnMap.put("IsDraftWhenSaveFail", true);
        pickToReturnMap.put("CustomParams", new VtuzxMap());
        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        param.append("PRD_MO", pickToReturnMap);

        List<VtuzxMap> prdToReturnStockList = kingdeeService.push(client, "PRD_PPBOM", pickToReturnMap);
        VtuzxMap prdToReturnStocks = prdToReturnStockList.get(0);
        String pickToReturnId = VtuzxUtil.getString(prdToReturnStocks, "Id");
        //修改退料单
        List<VtuzxMap> returnQuery = kingdeeService.query(client, "PRD_ReturnMtrl", new VtuzxArrayList<>(
                        "FBillNo",
                        "FEntity_FEntryID",
                        "FMaterialId.FNumber",
                        "FLot.FNumber",
                        "FQty"
                ),
                String.format("FID = '%s'", pickToReturnId), null, 0, 0);
        if (VtuzxUtil.isEmpty(returnQuery)) return;

        //计算每条分录的最大退单数从用料清单查询
        VtuzxMap countDataMap = new VtuzxMap();
        //查询用料清单
        List<VtuzxMap> prdBomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                        "FBillNo",
                        "FLot.FNumber",
                        "FMaterialID2.FNumber",
                        "FMaterialName1",
                        "FPickedQty",//已领数量
                        "FRePickedQty",//补领数量
                        "FScrapQty",//报废数量
                        "FGoodReturnQty",//良品退料数量
                        "FSelPrcdReturnQty",//退料选单数量
                        "FConsumeQty"//消耗数量

                ),
                String.format("FMOBillNO = '%s'", kingdeeBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(prdBomQuery)) return;
        for (VtuzxMap prdBomMap : prdBomQuery) {
            String fMaterialNo = VtuzxUtil.getString(prdBomMap, "FMaterialID2.FNumber");
            String batchNo = VtuzxUtil.getString(prdBomMap, "FLot.FNumber");
            BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap, "FPickedQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();
            double FPickedQtyCount = BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap, "FPickedQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();//已领数量
            double FRePickedQtyCount = BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap, "FRePickedQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();//补领数量
            double FScrapQtyCount = BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap, "FScrapQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();//报废数量
//            double FSelPrcdReturnQtyCount = BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap,"FSelPrcdReturnQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();//退料选单数量
            double FGoodReturnQty = BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap, "FGoodReturnQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();//良品退料选单数量
            double FConsumeQtyCount = BigDecimal.valueOf(VtuzxUtil.getDouble(prdBomMap, "FConsumeQty")).setScale(2, RoundingMode.HALF_UP).doubleValue();//消耗数量
            double count = FPickedQtyCount + FRePickedQtyCount - FScrapQtyCount - FGoodReturnQty - FConsumeQtyCount;
            count = BigDecimal.valueOf(count).setScale(2, RoundingMode.HALF_UP).doubleValue();
            double getCount = VtuzxUtil.getDouble(countDataMap, fMaterialNo + "_" + batchNo);
            if (getCount == 0) {
                countDataMap.put(fMaterialNo + "_" + batchNo, count);
            } else {
                countDataMap.put(fMaterialNo + "_" + batchNo, count + getCount);
            }

        }
        Document prdTaskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String produceHouseName = VtuzxUtil.getString(prdTaskDoc, "produceHouseName");
        //水袋的变品批次是6的话品项需要是领料或者补料的品,干参的变品不需要跟领料或者补料的一样
        //根据生产车间判断是干参的变品还是水袋的变品
        //按照变品退料单的数量，在退料单中按默认排序减去数量
        List<Map<String, Object>> prdReturnStockList = new ArrayList<>();
        Map<String, Object> prdReturnStockParam = new LinkedHashMap<>();
        Map<String, Object> prdReturnStockModel = new LinkedHashMap<>();
        if ("干参包装车间".equals(produceHouseName)) {
            for (VtuzxMap returnMap : returnQuery) {
                Map<String, Object> prdReturnStockMap = new LinkedHashMap<>();
                String returnEntryId = VtuzxUtil.getString(returnMap, "FEntity_FEntryID");
                String fMaterialNo = VtuzxUtil.getString(returnMap, "FMaterialId.FNumber");
                String batchNo = VtuzxUtil.getString(returnMap, "FLot.FNumber");
                double fQty = VtuzxUtil.getDouble(countDataMap, fMaterialNo + "_" + batchNo);
                double returnQty = VtuzxUtil.getDouble(returnMap, "FQty");
                if (returnQty > 0) {
                    if (desCount >= returnQty) {
                        prdReturnStockMap.put("FEntryID", returnEntryId);
                        prdReturnStockMap.put("FQty", returnQty);
                        prdReturnStockMap.put("FAPPQty", returnQty);
                        prdReturnStockList.add(prdReturnStockMap);
                    } else {
                        prdReturnStockMap.put("FEntryID", returnEntryId);
                        prdReturnStockMap.put("FQty", desCount);
                        prdReturnStockMap.put("FAPPQty", desCount);
                        prdReturnStockMap.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                        prdReturnStockList.add(prdReturnStockMap);
                    }
                    desCount -= returnQty;
                    if (desCount <= 0) break;

                }
            }
        } else { //水袋的变品
            for (VtuzxMap returnMap : returnQuery) {
                Map<String, Object> prdReturnStockMap = new LinkedHashMap<>();
                String returnEntryId = VtuzxUtil.getString(returnMap, "FEntity_FEntryID");
                String fMaterialNo = VtuzxUtil.getString(returnMap, "FMaterialId.FNumber");
                String batchNo = VtuzxUtil.getString(returnMap, "FLot.FNumber");
                double fQty = VtuzxUtil.getDouble(countDataMap, fMaterialNo + "_" + batchNo);
                double returnQty = VtuzxUtil.getDouble(returnMap, "FQty");
                if (fMaterialNo.equals(desMaterialNo)) {
                    if (returnQty > 0) {
                        if (desCount >= returnQty) {
                            prdReturnStockMap.put("FEntryID", returnEntryId);
                            prdReturnStockMap.put("FQty", returnQty);
                            prdReturnStockMap.put("FAPPQty", returnQty);
                            prdReturnStockMap.put("FStockId", new VtuzxMap("FNumber", desStockNo));
                            prdReturnStockMap.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                            prdReturnStockList.add(prdReturnStockMap);
                        } else {
                            prdReturnStockMap.put("FEntryID", returnEntryId);
                            prdReturnStockMap.put("FQty", desCount);
                            prdReturnStockMap.put("FAPPQty", desCount);
                            prdReturnStockMap.put("FStockId", new VtuzxMap("FNumber", desStockNo));
                            prdReturnStockMap.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                            prdReturnStockList.add(prdReturnStockMap);
                        }
                        desCount -= returnQty;
                        if (desCount <= 0) break;

                    }
                }
            }
        }

        prdReturnStockModel.put("FID", pickToReturnId);
        prdReturnStockModel.put("F_sctld_ZTDJH", billNo);//中台单据号
        if(!VtuzxUtil.isEmpty(desaltingTime) && !desaltingTime.equals("Invalid Date")){
            prdReturnStockModel.put("F_sctld_ZTTLSJ", desaltingTime);//中台退料时间
        } else {
            prdReturnStockModel.put("F_sctld_ZTTLSJ", desAuditTime);//中台退料时间
        }
        prdReturnStockModel.put("FDate", desCreateTime);//修改日期
        /*20251015===日期*/
        /*prdReturnStockModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));//修改日期(当前时间)*/
        prdReturnStockModel.put("FEntity", prdReturnStockList);

        prdReturnStockParam.put("NeedUpDateFields", new ArrayList<>());
        prdReturnStockParam.put("NeedReturnFields", new ArrayList<>());
        prdReturnStockParam.put("IsDeleteEntry", true);
        prdReturnStockParam.put("SubSystemId", "");
        prdReturnStockParam.put("IsVerifyBaseDataField", false);
        prdReturnStockParam.put("IsEntryBatchFill", true);
        prdReturnStockParam.put("ValidateFlag", true);
        prdReturnStockParam.put("NumberSearch", true);
        prdReturnStockParam.put("InterationFlags", "");
        prdReturnStockParam.put("Model", prdReturnStockModel);
        param.append("PRD_ReturnMtrl", prdReturnStockParam);
        String returnBillNumber = "";//变品退料单号
        try {
            List<VtuzxMap> inStockList = kingdeeService.save(client, "PRD_ReturnMtrl", prdReturnStockParam);
            VtuzxMap inStock = inStockList.get(0);
            returnBillNumber = VtuzxUtil.getString(inStock, "Number");
            kingdeeService.submit(client, "PRD_ReturnMtrl", "0", returnBillNumber);
            kingdeeService.audit(client, "PRD_ReturnMtrl", "0", returnBillNumber, "STK_InvCheckResult");
        } catch (Exception e) {
            _logger.info(e.getMessage());
        }

        //变品数量做生产订单
        Document taskDoc = prdTaskDao.findOne(Criteria.where("billNo").is(taskBillNo));
        String produceHouseNo = VtuzxUtil.getString(taskDoc, "produceHouseNo");
        String createUserName = VtuzxUtil.getString(taskDoc, "createUserName");
        String auditUserName = VtuzxUtil.getString(taskDoc, "auditUserName");

        //查询金蝶部门
        /*List<VtuzxMap> departmentQuery = kingdeeService.query(client, "BD_Department", new VtuzxArrayList<>(
                        "FNumber1",
                        "FNumber"
                ),
                String.format("FNumber1 = '%s'", produceHouseNo), null, 0, 1);
        if (VtuzxUtil.isEmpty(departmentQuery)) {
            throw new VtuzxException(String.format("部门[%s]在金蝶中不存在", produceHouseNo));
        }
        String department = VtuzxUtil.getString(departmentQuery.get(0), "FNumber");*/


        List<String> desKingdeeBillNoList = new ArrayList<>();
        //如果有全是6批次的做批次调整，否则正常走变品
        if (!VtuzxUtil.isEmpty(desaltingList)) {
            //批次调整
            syncBatchAndExpBn(desaltingList, historyDoc, taskBillNo, returnBillNumber);
        } else {
            //变品
            for (Document desaltingInDetail : desaltingInDetailList) { //按物料区分做订单
                List<Map<String, Object>> fOutStockEntry = new ArrayList<>();
                VtuzxMap prdOrderParam = new VtuzxMap();
                Map<String, Object> prdOrderModel = new LinkedHashMap<>();
                String materialNo = VtuzxUtil.getString(desaltingInDetail, "materialNo");
                Document materialDoc = materialDao.findOne(Criteria.where("fNumber").is(materialNo));
                if (VtuzxUtil.isEmpty(materialDoc)) {
                    throw new VtuzxException(String.format("编码为[%s]的物料不存在", materialNo));
                }
                String unit = VtuzxUtil.getString(materialDoc, "fBaseUnitIdNumber");
                double count = Math.abs(VtuzxUtil.getDouble(desaltingInDetail, "count"));
                String typeName = type.equals("product") ? "半成品、产成品" : "分选";
                Map<String, Object> detailMap = new LinkedHashMap<>();
                detailMap.put("FProductType", "1");
                detailMap.put("FMaterialId", new VtuzxMap("FNumber", materialNo));
                detailMap.put("FWorkShopID", new VtuzxMap("FNumber", "BM000004"));
                detailMap.put("FUnitId", new VtuzxMap("FNumber", unit));
                detailMap.put("FQty", count);
                detailMap.put("FYieldQty", count);
                /*detailMap.put("FPlanStartDate", desCreateTime);//计划开工日期
                detailMap.put("FPlanFinishDate", desAuditTime);*/
                detailMap.put("FRequestOrgId", new VtuzxMap("FNumber", "200"));
                detailMap.put("FISBACKFLUSH", true);
                detailMap.put("FStockInOrgId", new VtuzxMap("FNumber", "200"));
                detailMap.put("FBaseYieldQty", count);
                detailMap.put("FInStockOwnerTypeId", "BD_OwnerOrg");
                detailMap.put("FBaseStockInLimitH", count);
                detailMap.put("FInStockOwnerId", new VtuzxMap("FNumber", "200"));
                detailMap.put("FCheckProduct", false);
                detailMap.put("FBaseStockInLimitL", count);
                detailMap.put("FBaseUnitQty", count);
                detailMap.put("FBaseUnitId", new VtuzxMap("FNumber", unit));
                detailMap.put("FStockInLimitH", count);
                detailMap.put("FStockInLimitL", count);
                detailMap.put("FCostRate", 100.0);
                detailMap.put("FCreateType", "1");
                detailMap.put("FYieldRate", 100.0);
                detailMap.put("FGroup", "1");
                detailMap.put("FNoStockInQty", count);
                detailMap.put("FBaseNoStockInQty", count);
                detailMap.put("FRowId", "ba36ddd9-bb80-80b7-11ed-4f73ea562f1d");
                detailMap.put("FScheduleStatus", "1");
                detailMap.put("FPickMtrlStatus", "1");
                detailMap.put("FMOChangeFlag", false);
                detailMap.put("FIsFirstInspect", false);
                detailMap.put("FFirstInspectStatus", "A");
                detailMap.put("FSTOCKID", new VtuzxMap("FNumber", "002"));
                fOutStockEntry.add(detailMap);

                prdOrderModel.put("FID", 0);
                prdOrderModel.put("FBillType", new VtuzxMap("FNumber", "SCDD03_SYS"));
                prdOrderModel.put("FDate", desCreateTime);
                /*20251015===日期*/
                /*prdOrderModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));*/
                prdOrderModel.put("FPrdOrgId", new VtuzxMap("FNumber", "200"));
                prdOrderModel.put("FWorkShopID0", new VtuzxMap("FNumber", "BM000004"));
                prdOrderModel.put("FOwnerTypeId", "BD_OwnerOrg");
                prdOrderModel.put("FIsRework", false);
                prdOrderModel.put("FBusinessType", "1");
                prdOrderModel.put("FTrustteed", false);
                prdOrderModel.put("FIsEntrust", false);
                prdOrderModel.put("FPPBOMType", "1");
                prdOrderModel.put("FIssueMtrl", false);
                prdOrderModel.put("F_scdd_ZTSQR", createUserName);
                prdOrderModel.put("F_scdd_ZTSQSJ", desCreateTime);
                prdOrderModel.put("F_scdd_ZTSHR", auditUserName);
                prdOrderModel.put("F_scdd_ZTDJH", taskBillNo);
                prdOrderModel.put("F_scdd_SJLY", source);
                prdOrderModel.put("F_scdd_ZTSHSJ", desCreateTime);
                prdOrderModel.put("F_PSUH_DJLX", typeName);
                prdOrderModel.put("FTreeEntity", fOutStockEntry);

                prdOrderParam.append("Model", prdOrderModel);
                historyDoc.append("param", new VtuzxMap("PRD_MO", prdOrderParam));
                List<VtuzxMap> stkOutStockList = kingdeeService.save(client, "PRD_MO", prdOrderParam);
                VtuzxMap stkOutStockMap = stkOutStockList.get(0);
                String number = VtuzxUtil.getString(stkOutStockMap, "Number");
                kingdeeService.submit(client, "PRD_MO", "0", number);
                kingdeeService.audit(client, "PRD_MO", "0", number, "STK_InvCheckResult");
                desKingdeeBillNoList.add(number);
            }


            //查询退料单 按照退料单修改用料清单
            List<VtuzxMap> returnMaterialOrderQuery = kingdeeService.query(client, "PRD_ReturnMtrl", new VtuzxArrayList<>(
                            "FBillNo",
                            "FEntity_FEntryID",
                            "FMaterialId.FNumber",
                            "FStockId.FNumber",
                            "FQty",
                            "FUnitID.FNumber",
                            "FLot.FNumber"
                    ),
                    String.format("FID = '%s'", pickToReturnId), null, 0, 0);
            if (VtuzxUtil.isEmpty(returnMaterialOrderQuery)) return;

            int desNo = 0; //记录这是第几个订单
            for (String desKingdeeBillNo : desKingdeeBillNoList) {
                desNo++;
                List<Map<String, Object>> fMaterialBomEntry = new ArrayList<>();
                //根据生产订单单号找到对应用料清单
                List<VtuzxMap> materialBomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                                "FID",
                                "FBillNo",
                                "FMOBillNO",
                                "FMaterialID2.FNumber",
                                "FUnitID2.FNumber",
                                "FNeedQty2",
                                "FEntity_FEntryID"
                        ),
                        String.format("FMOBillNO = '%s'", desKingdeeBillNo), null, 0, 0);
                if (VtuzxUtil.isEmpty(materialBomQuery)) return;
                String fid = VtuzxUtil.getString(materialBomQuery.get(0), "FID");
                String entryId = VtuzxUtil.getString(materialBomQuery.get(0), "FEntity_FEntryID");

                //留一个原单据的分录
                materialPickInner(materialBomQuery.get(0), fMaterialBomEntry);
                for (VtuzxMap returnMaterialOrder : returnMaterialOrderQuery) {
                    String materialNo = VtuzxUtil.getString(returnMaterialOrder, "FMaterialId.FNumber");
                    String unit = VtuzxUtil.getString(returnMaterialOrder, "FUnitID.FNumber");
                    String batchNo = VtuzxUtil.getString(returnMaterialOrder, "FLot.FNumber");
                    String stockNo = VtuzxUtil.getString(returnMaterialOrder, "FStockId.FNumber");
                    double fQty = VtuzxUtil.getDouble(returnMaterialOrder, "FQty");
                    double lineCount;
                    if (desNo == desKingdeeBillNoList.size()) { // 如果是最后一行
                        lineCount = fQty - (BigDecimal.valueOf(fQty / returnMaterialOrderQuery.size()).setScale(2, RoundingMode.HALF_UP).doubleValue() * (desNo - 1));
                    } else {
                        lineCount = BigDecimal.valueOf(fQty / returnMaterialOrderQuery.size()).setScale(2, RoundingMode.HALF_UP).doubleValue();
                    }
                    Map<String, Object> materialBoms = new LinkedHashMap<>();
                    materialBoms.put("FMaterialID2", new VtuzxMap("FNumber", materialNo));
                    materialBoms.put("FMaterialType", "1");
                    materialBoms.put("FSupplyType", "");
                    materialBoms.put("FDosageType", "2");
                    materialBoms.put("FNumerator", 1);//分子
                    materialBoms.put("FDenominator", 1);//分母
                    materialBoms.put("FUnitID2", new VtuzxMap("FNumber", unit));
                    materialBoms.put("FFixScrapQty", 0);
                    materialBoms.put("FScrapRate", 0);
//                    materialBoms.put("FNeedDate2", "2022-10-10");
                    materialBoms.put("FStdQty", lineCount);
                    materialBoms.put("FNeedQty2 ", lineCount);
                    materialBoms.put("FMustQty", lineCount);
                    materialBoms.put("FSupplyOrg", new VtuzxMap("FNumber", "200"));
                    materialBoms.put("FIsKeyComponent", false);
                    materialBoms.put("FBomId2", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FAllowOver", false);
                    materialBoms.put("FWorkCalId2", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FBaseNumerator", 1);
                    materialBoms.put("FReserveType", "");
                    materialBoms.put("FBASEDENOMINATOR", 1);
                    materialBoms.put("FSMEntryId", 0);
                    materialBoms.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                    materialBoms.put("FEntrustPickOrgId", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FOperID", 0);
                    materialBoms.put("FLot", new VtuzxMap("FNumber", batchNo));
                    materialBoms.put("FStockId", new VtuzxMap("FNumber", stockNo)); //取第一次领料的单据
                    materialBoms.put("FOffsetTime", 0);
                    materialBoms.put("FProcessID", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FIssueType", "1");
                    materialBoms.put("FSrcTransOrgId", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FSrcTransStockId", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FNoPickedQty", 0);
                    materialBoms.put("FInventoryQty", 0);
                    materialBoms.put("FIsSkip", false);
                    materialBoms.put("FISMinIssueQty", false);
                    materialBoms.put("FIsGetScrap", false);
                    materialBoms.put("FPPBomEntryType", "0");
                    materialBoms.put("FUPDATERID", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FUPDateDate", "2022-10-10");
                    materialBoms.put("FOwnerTypeId", "BD_OwnerOrg");
                    materialBoms.put("FSupplyMode", "z");
                    materialBoms.put("FBaseNoPickedQty", 0);
                    materialBoms.put("FIsMrpRun", false);
                    materialBoms.put("FSrcPPBOMID", 0);
                    materialBoms.put("FSrcPPBOMEntryId", 0);
                    materialBoms.put("FStockReadyQty", 0);
                    materialBoms.put("FBaseStockReadyQty", 0);
                    materialBoms.put("FBaseUnitID1", new VtuzxMap("FNumber", unit));
                    materialBoms.put("FReturnNoOkQty", 0);
                    materialBoms.put("FMoType1", new VtuzxMap("FNumber", "SCDD03_SYS"));
                    materialBoms.put("FOwnerID", new VtuzxMap("FNumber", "200"));
                    materialBoms.put("FGroupByOwnerId", new VtuzxMap("FNumber", ""));
                    materialBoms.put("FIsExpand", false);
                    materialBoms.put("FCheckReturnMtrl", false);
                    materialBoms.put("FBaseReturnAppSelQty", 0);
                    materialBoms.put("FReturnAppSelQty", 0);
                    fMaterialBomEntry.add(materialBoms);
                }

                Map<String, Object> prdPickOrderParam = new LinkedHashMap<>();
                Map<String, Object> prdPickOrderModel = new LinkedHashMap<>();
                prdPickOrderModel.put("FID", fid);
                prdPickOrderModel.put("FEntity", fMaterialBomEntry);

                prdPickOrderParam.put("NeedUpDateFields", new ArrayList<>());
                prdPickOrderParam.put("NeedReturnFields", new ArrayList<>());
                prdPickOrderParam.put("IsDeleteEntry", true);
                prdPickOrderParam.put("SubSystemId", "");
                prdPickOrderParam.put("IsVerifyBaseDataField", true);
                prdPickOrderParam.put("IsEntryBatchFill", false);
                prdPickOrderParam.put("ValidateFlag", true);
                prdPickOrderParam.put("NumberSearch", true);
                prdPickOrderParam.put("InterationFlags", "");
                prdPickOrderParam.put("Model", prdPickOrderModel);
                param.append("PRD_PPBOM", prdPickOrderParam);
                kingdeeService.save(client, "PRD_PPBOM", prdPickOrderParam);

                //查新增后的分录id
                List<VtuzxMap> materialBomTwoQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                                "FID",
                                "FBillNo",
                                "FMOBillNO",
                                "FMaterialID2.FNumber",
                                "FUnitID2.FNumber",
                                "FNeedQty2",
                                "FEntity_FEntryID"
                        ),
                        String.format("FMOBillNO = '%s'", desKingdeeBillNo), null, 0, 0);

                if (VtuzxUtil.isEmpty(materialBomTwoQuery)) return;

                List<Map<String, Object>> entryIdList = new ArrayList<>();
                for (VtuzxMap materialBomTwo : materialBomTwoQuery) {
                    Map<String, Object> map = new LinkedHashMap<>();
                    String fEntryID = VtuzxUtil.getString(materialBomTwo, "FEntity_FEntryID");
                    if (!fEntryID.equals(entryId)) {
                        map.put("FEntryID", fEntryID);
                        entryIdList.add(map);
                    }
                }

                Map<String, Object> prdPickOrderTwoParam = new LinkedHashMap<>();
                Map<String, Object> prdPickOrderTwoModel = new LinkedHashMap<>();

                prdPickOrderTwoModel.put("FID", fid);
                prdPickOrderTwoModel.put("FEntity", entryIdList);

                prdPickOrderTwoParam.put("NeedUpDateFields", new ArrayList<>());
                prdPickOrderTwoParam.put("NeedReturnFields", new ArrayList<>());
                prdPickOrderTwoParam.put("IsDeleteEntry", true);
                prdPickOrderTwoParam.put("SubSystemId", "");
                prdPickOrderTwoParam.put("IsVerifyBaseDataField", true);
                prdPickOrderTwoParam.put("IsEntryBatchFill", false);
                prdPickOrderTwoParam.put("ValidateFlag", true);
                prdPickOrderTwoParam.put("NumberSearch", true);
                prdPickOrderTwoParam.put("InterationFlags", "");
                prdPickOrderTwoParam.put("Model", prdPickOrderTwoModel);
                param.append("PRD_PPBOM", prdPickOrderTwoParam);
                List<VtuzxMap> prdPPBomsList = kingdeeService.save(client, "PRD_PPBOM", prdPickOrderTwoParam);
                VtuzxMap prdPPBomsMap = prdPPBomsList.get(0);
                String bomNumber = VtuzxUtil.getString(prdPPBomsMap, "Number");
                kingdeeService.submit(client, "PRD_PPBOM", "0", bomNumber);
                kingdeeService.audit(client, "PRD_PPBOM", "0", bomNumber, "STK_InvCheckResult");

                //生产订单执行至开工
                kingdeeService.toRelease(client, "PRD_MO", "ToStart", "0", desKingdeeBillNo);
                //修改生产订单下达时间
                try {
                    kingdeeService.orderUpdate(client, "PRD_MO", desKingdeeBillNo, desCreateTime);
                } catch (Exception e) {
                    _logger.info(e.getMessage());
                }
                //TODO
                //用料清单下推生产领料
                List<String> bomNumberList = new ArrayList<>();
                bomNumberList.add(bomNumber);
                Map<String, Object> bomToPickMap = new LinkedHashMap<>();
                bomToPickMap.put("Ids", "");
                bomToPickMap.put("Numbers", bomNumberList);
                bomToPickMap.put("EntryIds", "");
                bomToPickMap.put("RuleId", VtuzxUtil.getString(prdPushRuleDao.findOne(Criteria
                        .where("ruleName").is("PPBOMPushPickMtrl")
                        .and("ruleType").is("desalting")
                        .and("tokenType").is("kingdee3")
                ), "ruleId"));
                bomToPickMap.put("TargetBillTypeId", "");
                bomToPickMap.put("TargetOrgId", 0);
                bomToPickMap.put("IsEnableDefaultRule", false);
                bomToPickMap.put("IsDraftWhenSaveFail", false);
                bomToPickMap.put("CustomParams", new VtuzxMap());
                param.append("PRD_PPBOM", bomToPickMap);
                List<VtuzxMap> pickBillList = kingdeeService.push(client, "PRD_PPBOM", bomToPickMap);
                VtuzxMap pickBillMap = pickBillList.get(0);
                String desPickBillNo = VtuzxUtil.getString(pickBillMap, "Number");
                String id = VtuzxUtil.getString(pickBillMap, "Id");

                Map<String, Object> updatePickParam = new LinkedHashMap<>();
                Map<String, Object> updatePickModel = new LinkedHashMap<>();

                updatePickModel.put("FID", id);
                updatePickModel.put("Fdate", desCreateTime);
                /*20251015===日期*/
                /*updatePickModel.put("Fdate", VtuzxUtil.formatYmdHmsF(new Date()));*/
                updatePickModel.put("F_sclld_ZTLLR", createUserName);
                updatePickModel.put("F_sclld_ZTDJH", billNo);
                updatePickModel.put("F_sclld_SJLY", source);
                updatePickModel.put("F_sclld_ZTLLSJ", desCreateTime);

                updatePickParam.put("NeedUpDateFields", new ArrayList<>());
                updatePickParam.put("NeedReturnFields", new ArrayList<>());
                updatePickParam.put("IsDeleteEntry", true);
                updatePickParam.put("SubSystemId", "");
                updatePickParam.put("IsVerifyBaseDataField", true);
                updatePickParam.put("IsEntryBatchFill", false);
                updatePickParam.put("ValidateFlag", true);
                updatePickParam.put("NumberSearch", true);
                updatePickParam.put("InterationFlags", "");
                updatePickParam.put("Model", updatePickModel);

                param.append("PRD_PickMtrl", updatePickParam);
                try {
                    kingdeeService.save(client, "PRD_PickMtrl", updatePickParam);
                    kingdeeService.submit(client, "PRD_PickMtrl", "0", desPickBillNo);
                    kingdeeService.audit(client, "PRD_PickMtrl", "0", desPickBillNo, "STK_InvCheckResult");

                } catch (Exception e) {
                    _logger.info(e.getMessage());
                }


                //生产订单下推入库
                List<String> prdBillNoList = new ArrayList<>();
                prdBillNoList.add(desKingdeeBillNo);
                Map<String, Object> prdToInStockMap = new LinkedHashMap<>();
                prdToInStockMap.put("Ids", "");
                prdToInStockMap.put("Numbers", prdBillNoList);
                prdToInStockMap.put("EntryIds", "");
                prdToInStockMap.put("RuleId", VtuzxUtil.getString(prdPushRuleDao.findOne(Criteria
                        .where("ruleName").is("MOPushINSTOCK")
                        .and("ruleType").is("desalting")
                        .and("tokenType").is("kingdee3")
                ), "ruleId"));
                prdToInStockMap.put("TargetBillTypeId", "");
                prdToInStockMap.put("TargetOrgId", 0);
                prdToInStockMap.put("IsEnableDefaultRule", false);
                prdToInStockMap.put("IsDraftWhenSaveFail", false);
                prdToInStockMap.put("CustomParams", new VtuzxMap());

                List<VtuzxMap> prdToInStockList = kingdeeService.push(client, "PRD_MO", prdToInStockMap);
                VtuzxMap prdToInStocks = prdToInStockList.get(0);
                String prdToInStockBillNo = VtuzxUtil.getString(prdToInStocks, "Number");

                //查询生产入库
                List<VtuzxMap> inStockQuery = kingdeeService.query(client, "PRD_INSTOCK", new VtuzxArrayList<>(
                                "FID",
                                "FBillNo",
                                "FEntity_FEntryID",
                                "FMaterialId.FNumber",
                                "FRealQty"
                        ),
                        String.format("FBillNo = '%s'", prdToInStockBillNo), null, 0, 1);
                if (VtuzxUtil.isEmpty(inStockQuery)) return;
                VtuzxMap inStockMap = inStockQuery.get(0);
                String inStockId = VtuzxUtil.getString(inStockMap, "FID");


                List<Map<String, Object>> prdInStockList = new ArrayList<>();
                Map<String, Object> prdInStockParam = new LinkedHashMap<>();
                Map<String, Object> prdInStockModel = new LinkedHashMap<>();
                //修改入库
                for (VtuzxMap inMap : inStockQuery) {
                    String inStockEntryId = VtuzxUtil.getString(inMap, "FEntity_FEntryID");
                    String inMaterialNo = VtuzxUtil.getString(inMap, "FMaterialId.FNumber");
                    for (Document desaltingInDetail : desaltingInDetailList) {
                        String materialNo = VtuzxUtil.getString(desaltingInDetail, "materialNo");
                        String batchNo = VtuzxUtil.getString(desaltingInDetail, "batchNo");
                        String stockNo = VtuzxUtil.getString(desaltingInDetail, "stockNo");
                        Map<String, Object> entryMap = new LinkedHashMap<>();
                        if (inMaterialNo.equals(materialNo)) {
                            entryMap.put("FEntryID", inStockEntryId);
                            /*entryMap.put("fStockId", new VtuzxMap("FNumber", stockNo));*/
                            /*if(CP_WAREHOUSECODE.contains(stockNo)){
                                entryMap.put("fStockId", new VtuzxMap("FNumber", "001"));
                            } else{
                                entryMap.put("fStockId", new VtuzxMap("FNumber", "002"));
                            }*/
                            //20251014生产成品“委外库”
                            entryMap.put("fStockId", new VtuzxMap("FNumber", "002"));
                            entryMap.put("FLot", new VtuzxMap("FNumber", batchNo));
                            entryMap.put("FStockStatusId", new VtuzxMap("FNumber", "KCZT01_SYS"));
                            prdInStockList.add(entryMap);
                        }
                    }
                }

                prdInStockModel.put("FID", inStockId);
                prdInStockModel.put("FDate", desCreateTime);
                /*20251015===日期*/
                /*prdInStockModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));*/
                prdInStockModel.put("F_scrkd_ZTRKR", createUserName);
                prdInStockModel.put("F_scrkd_ZTRKSJ", desCreateTime);
                prdInStockModel.put("F_scrkd_ZTDJH", billNo);
                prdInStockModel.put("F_scrkd_SJLY", source);
                prdInStockModel.put("FEntity", prdInStockList);

                prdInStockParam.put("NeedUpDateFields", new ArrayList<>());
                prdInStockParam.put("NeedReturnFields", new ArrayList<>());
                prdInStockParam.put("IsDeleteEntry", false);
                prdInStockParam.put("SubSystemId", "");
                prdInStockParam.put("IsVerifyBaseDataField", false);
                prdInStockParam.put("IsEntryBatchFill", true);
                prdInStockParam.put("ValidateFlag", true);
                prdInStockParam.put("NumberSearch", true);
                prdInStockParam.put("InterationFlags", "");
                prdInStockParam.put("Model", prdInStockModel);

                param.append("PRD_INSTOCK", prdInStockParam);
                List<VtuzxMap> prdInList = kingdeeService.save(client, "PRD_INSTOCK", prdInStockParam);
                VtuzxMap prdInMap = prdInList.get(0);
                String inNumber = VtuzxUtil.getString(prdInMap, "Number");
                kingdeeService.submit(client, "PRD_INSTOCK", "0", inNumber);
                kingdeeService.audit(client, "PRD_INSTOCK", "0", inNumber, "STK_InvCheckResult");
            }
        }

    }

    //退料的批次调整单
    private void syncBatchAndExp(List<Document> desaltingList, String taskBillNo, String returnBillNumber) throws Exception {
        //金蝶token
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        Map<String, Object> batchParam = new HashMap<>();//传单param
        Map<String, Object> batchModel = new HashMap<>();//单据头
        List<Map<String, Object>> batchList = new ArrayList<>();//单据体
        Date createTime = VtuzxUtil.getObject(desaltingList.get(0), "createTime");
        String zBatchNo = VtuzxUtil.getString(desaltingList.get(0), "batchNo");
//        String stockNo =  VtuzxUtil.getString(desaltingList.get(0),"stockNo");

        //查询转换前的仓库和批号
        String returnCond = String.format("FBillNo = '%s'", returnBillNumber);
        List<VtuzxMap> bd_return = kingdeeService.query(client, "PRD_ReturnMtrl", new VtuzxArrayList<>(
                "FStockId.Fnumber",//仓库
                "FLot.FNumber",//批次
                "FQty",
                "FUnitID.FNumber",
                "FMaterialId.FNumber"
        ), returnCond);
        int groupNum = 1;//单据体分组字段
        for (VtuzxMap returnMap : bd_return) {
            String pickStockNo = VtuzxUtil.getString(returnMap, "FStockId.Fnumber");
            String pickBatchNo = VtuzxUtil.getString(returnMap, "FLot.FNumber");
            double fQty = VtuzxUtil.getDouble(returnMap, "FQty");
            String unit = VtuzxUtil.getString(returnMap, "FUnitID.FNumber");
            String materialNo = VtuzxUtil.getString(returnMap, "FMaterialId.FNumber");

            //转换前
            Map<String, Object> batchEntry = new LinkedHashMap<>();
            batchEntry.put("FGroup", groupNum);
            batchEntry.put("FConvertType", "A");//转换类型
            batchEntry.put("FMATERIALID", new Document("FNumber", materialNo));//物料
            batchEntry.put("FLot", new Document("FNumber", pickBatchNo));//批号
            batchEntry.put("FUnitID", new Document("FNumber", unit));//单位
            batchEntry.put("FQty", fQty);//转换数量
            batchEntry.put("FSTOCKID", new Document("FNumber", pickStockNo));//仓库
            batchEntry.put("FStockStatusId", new Document("FNumber", "KCZT01_SYS"));//库存状态
            batchEntry.put("FKeeperTypeId", "BD_KeeperOrg");//保管者类型
            batchEntry.put("FKeeperId", new Document("FNumber", "100"));//保管者
            batchEntry.put("FOwnerTypeId", "BD_OwnerOrg");//货主类型
            batchEntry.put("FOwnerId", new Document("FNumber", "100"));//货主
            batchList.add(batchEntry);

            //转换后
            Map<String, Object> afterEntry = new LinkedHashMap<>();
            afterEntry.put("FGroup", groupNum);
            afterEntry.put("FConvertType", "B");//转换类型
            afterEntry.put("FMATERIALID", new Document("FNumber", materialNo));//物料
            afterEntry.put("FLot", new Document("FNumber", zBatchNo));//批号
            afterEntry.put("FUnitID", new Document("FNumber", unit));//单位
            afterEntry.put("FQty", fQty);//转换数量
            afterEntry.put("FSTOCKID", new Document("FNumber", pickStockNo));//仓库
            afterEntry.put("FStockStatusId", new Document("FNumber", "KCZT01_SYS"));//库存状态
            afterEntry.put("FKeeperTypeId", "BD_KeeperOrg");//保管者类型
            afterEntry.put("FKeeperId", new Document("FNumber", "100"));//保管者
            afterEntry.put("FOwnerTypeId", "BD_OwnerOrg");//货主类型
            afterEntry.put("FOwnerId", new Document("FNumber", "100"));//货主
            batchList.add(afterEntry);
            groupNum++;

        }
        batchModel.put("FID", 0);//实体主键
        batchModel.put("FBillTypeID", new Document("FNUMBER", "PHTZ01_SYS"));//单据类型
        batchModel.put("FStockOrgId", new Document("FNumber", "100"));//库存组织
        batchModel.put("FDate", VtuzxUtil.formatYmdHmsF(createTime));
        batchModel.put("FOwnerTypeIdHead", "BD_OwnerOrg");//货主类型
        batchModel.put("FOwnerIdHead", new Document("FNumber", "100"));//
        batchModel.put("FSTK_LOTADJUSTENTRY", batchList);
        batchModel.put("F_ora_ZTDJH", taskBillNo);//中台单据号

        batchParam.put("NeedUpDateFields", new ArrayList<>());
        batchParam.put("NeedReturnFields", new ArrayList<>());
        batchParam.put("IsDeleteEntry", true);
        batchParam.put("SubSystemId", "");
        batchParam.put("IsVerifyBaseDataField", false);
        batchParam.put("IsEntryBatchFill", true);
        batchParam.put("ValidateFlag", true);
        batchParam.put("NumberSearch", true);
        batchParam.put("InterationFlags", "");
        batchParam.put("Model", batchModel);

        try {
            List<VtuzxMap> inStockList = kingdeeService.save(client, "STK_LOTADJUST", batchParam);
        } catch (Exception e) {
            _logger.info(e.getMessage());
        }


    }

    //退料的批次调整单BN
    private void syncBatchAndExpBn(List<Document> desaltingList, Document historyDoc,  String taskBillNo, String returnBillNumber) throws Exception {
        //金蝶token
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdeeYX();
        Map<String, Object> batchParam = new HashMap<>();//传单param
        Map<String, Object> batchModel = new HashMap<>();//单据头
        List<Map<String, Object>> batchList = new ArrayList<>();//单据体
        Date createTime = VtuzxUtil.getObject(desaltingList.get(0), "createTime");
        String zBatchNo = VtuzxUtil.getString(desaltingList.get(0), "batchNo");
        //String stockNo =  VtuzxUtil.getString(desaltingList.get(0),"stockNo");
        //查询转换前的仓库和批号
        String returnCond = String.format("FBillNo = '%s'", returnBillNumber);
        List<VtuzxMap> bd_return = kingdeeService.query(client, "PRD_ReturnMtrl", new VtuzxArrayList<>(
                "FStockId.Fnumber",//仓库
                "FLot.FNumber",//批次
                "FQty",
                "FUnitID.FNumber",
                "FMaterialId.FNumber"
        ), returnCond);
        int groupNum = 1;//单据体分组字段
        for (VtuzxMap returnMap : bd_return) {
            String pickStockNo = VtuzxUtil.getString(returnMap, "FStockId.Fnumber");
            String pickBatchNo = VtuzxUtil.getString(returnMap, "FLot.FNumber");
            double fQty = VtuzxUtil.getDouble(returnMap, "FQty");
            String unit = VtuzxUtil.getString(returnMap, "FUnitID.FNumber");
            String materialNo = VtuzxUtil.getString(returnMap, "FMaterialId.FNumber");
            //转换前
            Map<String, Object> batchEntry = new LinkedHashMap<>();
            batchEntry.put("FGroup", groupNum);
            batchEntry.put("FConvertType", "A");//转换类型
            batchEntry.put("FMATERIALID", new Document("FNumber", materialNo));//物料
            batchEntry.put("FLot", new Document("FNumber", pickBatchNo));//批号
            batchEntry.put("FUnitID", new Document("FNumber", unit));//单位
            batchEntry.put("FQty", fQty);//转换数量
            batchEntry.put("FSTOCKID", new Document("FNumber", pickStockNo));//仓库
            batchEntry.put("FStockStatusId", new Document("FNumber", "KCZT01_SYS"));//库存状态
            batchEntry.put("FKeeperTypeId", "BD_KeeperOrg");//保管者类型
            batchEntry.put("FKeeperId", new Document("FNumber", "200"));//保管者
            batchEntry.put("FOwnerTypeId", "BD_OwnerOrg");//货主类型
            batchEntry.put("FOwnerId", new Document("FNumber", "200"));//货主
            batchList.add(batchEntry);
            //转换后
            Map<String, Object> afterEntry = new LinkedHashMap<>();
            afterEntry.put("FGroup", groupNum);
            afterEntry.put("FConvertType", "B");//转换类型
            afterEntry.put("FMATERIALID", new Document("FNumber", materialNo));//物料
            afterEntry.put("FLot", new Document("FNumber", zBatchNo));//批号
            afterEntry.put("FUnitID", new Document("FNumber", unit));//单位
            afterEntry.put("FQty", fQty);//转换数量
            afterEntry.put("FSTOCKID", new Document("FNumber", pickStockNo));//仓库
            afterEntry.put("FStockStatusId", new Document("FNumber", "KCZT01_SYS"));//库存状态
            afterEntry.put("FKeeperTypeId", "BD_KeeperOrg");//保管者类型
            afterEntry.put("FKeeperId", new Document("FNumber", "200"));//保管者
            afterEntry.put("FOwnerTypeId", "BD_OwnerOrg");//货主类型
            afterEntry.put("FOwnerId", new Document("FNumber", "200"));//货主
            batchList.add(afterEntry);
            groupNum++;
        }
        batchModel.put("FID", 0);//实体主键
        batchModel.put("FBillTypeID", new Document("FNUMBER", "PHTZ01_SYS"));//单据类型
        batchModel.put("FStockOrgId", new Document("FNumber", "200"));//库存组织
        batchModel.put("FDate", VtuzxUtil.formatYmdHmsF(createTime));
        batchModel.put("FOwnerTypeIdHead", "BD_OwnerOrg");//货主类型
        batchModel.put("FOwnerIdHead", new Document("FNumber", "200"));//
        batchModel.put("FSTK_LOTADJUSTENTRY", batchList);
        batchModel.put("F_ora_ZTDJH", taskBillNo);//中台单据号
        batchParam.put("NeedUpDateFields", new ArrayList<>());
        batchParam.put("NeedReturnFields", new ArrayList<>());
        batchParam.put("IsDeleteEntry", true);
        batchParam.put("SubSystemId", "");
        batchParam.put("IsVerifyBaseDataField", false);
        batchParam.put("IsEntryBatchFill", true);
        batchParam.put("ValidateFlag", true);
        batchParam.put("NumberSearch", true);
        batchParam.put("InterationFlags", "");
        batchParam.put("Model", batchModel);
        try {
            List<VtuzxMap> inStockList = kingdeeService.save(client, "STK_LOTADJUST", batchParam);
            VtuzxMap inStockMap = inStockList.get(0);
            String number = VtuzxUtil.getString(inStockMap, "Number");
            kingdeeService.submit(client, "STK_LOTADJUST", "0", number);
            kingdeeService.audit(client, "STK_LOTADJUST", "0", number, "STK_InvCheckResult");
            historyDoc.append("kingdeeNumber", number);
            historyDoc.append("inStockOrder", true);
        } catch (Exception e) {
            _logger.info(e.getMessage());
        }
    }


    private void countDataInner(VtuzxMap countDataMap, Iterator<Document> materialItr, boolean isAdd) {
        while (materialItr.hasNext()) {
            Document materialDoc = materialItr.next();
            String materialNo = VtuzxUtil.getString(materialDoc, "materialNo");
            String batchNo = VtuzxUtil.getString(materialDoc, "batchNo");
            double count = VtuzxUtil.getDouble(materialDoc, "count");
            double sumCount = VtuzxUtil.getDouble(countDataMap, materialNo + "_" + batchNo);
            countDataMap.append(materialNo + "_" + batchNo, isAdd ? sumCount + count : sumCount - count);
        }
    }


    @Override
    public void syncPurOrderInStock(ObjectId userId, String name, String billNo, String orderNo, String source) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }


        Document bcPurInStockOrderDoc = purInDao.findOne(Criteria.where("billNo").is(billNo).and("isBc").is(true));
        int boxCount = VtuzxUtil.getInt(bcPurInStockOrderDoc, "boxCount");
        if (boxCount == 0) {
            historyDoc.append("purOrderInStock", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }
        historyDoc.append("billNo", billNo);//入库单号
        historyDoc.append("orderNo", orderNo);//采购单号
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", bcPurInStockOrderDoc);
        historyDoc.append("event", "bcPurInStock");

        try {
            syncPurOrderInStockInner(historyDoc);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("bcPurInStock", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    private void syncPurOrderInStockInner(Document historyDoc) throws Exception {
        String orderNo = VtuzxUtil.getString(historyDoc, "orderNo");
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");
        String userName = VtuzxUtil.getString(historyDoc, "userName");
        Document data = VtuzxUtil.getObject(historyDoc, "data");
        String createUserName = VtuzxUtil.getString(data, "createUserName");
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(data, "createTime"));
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();

        List<VtuzxMap> purOrderQuery = kingdeeService.query(client, "PUR_PurchaseOrder", new VtuzxArrayList<>(
                        "FBillNo"
                ),
                String.format("FBillNo = '%s'", orderNo), null, 0, 1);
        if (VtuzxUtil.isEmpty(purOrderQuery)) {
            throw new VtuzxException(String.format("金蝶不存在单号为[%s]的采购订单", orderNo));
        }
        //采购订单下推采购入库
        List<String> purBillNoList = new ArrayList<>();
        purBillNoList.add(orderNo);
        Map<String, Object> purToInStockMap = new LinkedHashMap<>();
        purToInStockMap.put("Ids", "");
        purToInStockMap.put("Numbers", purBillNoList);
        purToInStockMap.put("EntryIds", "");
        purToInStockMap.put("RuleId", "ora_ztxt");
        purToInStockMap.put("TargetBillTypeId", "");
        purToInStockMap.put("TargetOrgId", 0);
        purToInStockMap.put("IsEnableDefaultRule", false);
        purToInStockMap.put("IsDraftWhenSaveFail", false);
        purToInStockMap.put("CustomParams", new VtuzxMap());
        List<VtuzxMap> purToInStockList = kingdeeService.push(client, "PUR_PurchaseOrder", purToInStockMap);
        VtuzxMap purToInStocks = purToInStockList.get(0);
        String purToInStockBillNo = VtuzxUtil.getString(purToInStocks, "Number");
        String purToInStockId = VtuzxUtil.getString(purToInStocks, "Id");

        //查询下推后的采购入库单
        List<VtuzxMap> purOrderInQuery = kingdeeService.query(client, "STK_InStock", new VtuzxArrayList<>(
                        "FBillNo",
                        "FID",
                        "FInStockEntry_FEntryID",
                        "FMaterialId.FNumber"
                ),
                String.format("FBillNo = '%s'", purToInStockBillNo), null, 0, 0);

        List<Document> purInDetailList = new ArrayList<>();
        Iterator<Document> purInDetailItr = purInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (purInDetailItr.hasNext()) {
            Document purInDetailDoc = purInDetailItr.next();
            purInDetailList.add(purInDetailDoc);
        }

        Map<String, Object> paramMap = new LinkedHashMap<>();
        Map<String, Object> modelMap = new LinkedHashMap<>();
        List<Map<String, Object>> entryList = new ArrayList<>();
        for (VtuzxMap purOrderIn : purOrderInQuery) { //采购入库单分录
            Map<String, Object> entryMap = new LinkedHashMap<>();
            String fMaterialNo = VtuzxUtil.getString(purOrderIn, "FMaterialId.FNumber");
            String fEntryId = VtuzxUtil.getString(purOrderIn, "FInStockEntry_FEntryID");
            for (Document purInDetail : purInDetailList) { //中台采购入库单
                String materialNo = VtuzxUtil.getString(purInDetail, "materialNo");
                String stockNo = VtuzxUtil.getString(purInDetail, "stockNo");
                double count = VtuzxUtil.getDouble(purInDetail, "count");
                if (fMaterialNo.equals(materialNo)) {
                    entryMap.put("FEntryId", fEntryId);
                    entryMap.put("FRealQty", count);
                    entryMap.put("FStockId", new VtuzxMap("FNumber", stockNo));
                    entryList.add(entryMap);
                }
            }
        }
        modelMap.put("FID", purToInStockId);
        modelMap.put("FInStockEntry", entryList);
        modelMap.put("F_ora_ZTDJH", billNo);
        modelMap.put("F_ora_CZRY", userName);
        modelMap.put("F_ora_FHR", createUserName);
        modelMap.put("F_ora_SJLY", source);
        modelMap.put("F_ora_ZTYWRQ", createTime);

        paramMap.put("model", modelMap);
        historyDoc.append("param", new VtuzxMap("STK_InStock", paramMap));
        List<VtuzxMap> stkInStockList = kingdeeService.save(client, "STK_InStock", paramMap);
        VtuzxMap stkInStockMap = stkInStockList.get(0);
        String inStcokNumber = VtuzxUtil.getString(stkInStockMap, "Number");
        kingdeeService.submit(client, "STK_InStock", "0", inStcokNumber);
        kingdeeService.audit(client, "STK_InStock", "0", inStcokNumber, "STK_InvCheckResult");

    }

    @Override
    public void syncReturn(ObjectId userId, String name, String billNo, String source, String returnTime) throws Exception {

        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        Document prdReturnOrderDoc = prdInDao.findOne(Criteria.where("billNo").is(billNo));
        int boxCount = VtuzxUtil.getInt(prdReturnOrderDoc, "boxCount");
        if (boxCount == 0) {
            historyDoc.append("prdReturnOrder", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }

        historyDoc.append("billNo", billNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", prdReturnOrderDoc);
        historyDoc.append("event", "prdReturn");
        try {
            syncInnerReturn(historyDoc, returnTime);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdReturnOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    @Override
    public void syncReturnBn(ObjectId userId, String name, String billNo, String source, String returnTime) throws Exception {
        Document historyDoc = syncOrderDao.findOne(Criteria.where("billNo").is(billNo));
        ObjectId id = null;
        if (historyDoc == null) {
            historyDoc = new Document("billNo", billNo);
        } else {
            id = VtuzxUtil.getObject(historyDoc, "_id");
        }
        Document prdReturnOrderDoc = prdInDao.findOne(Criteria.where("billNo").is(billNo));
        /*int boxCount = VtuzxUtil.getInt(prdReturnOrderDoc, "boxCount");*/
        Iterator<Document> returnDetailItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        List<Document> validDetails = new ArrayList<>();
        while (returnDetailItr.hasNext()) {
            Document detail = returnDetailItr.next();
            String batchNo = VtuzxUtil.getString(detail, "batchNo");
            if (batchNo != null && batchNo.toUpperCase().startsWith("BN")) {
                validDetails.add(detail);
            }
        }
        int validBoxCount = validDetails.size();
        if (validBoxCount == 0) {
            historyDoc.append("prdReturnOrder", false).append("message", "单据分录为0").append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
            return;
        }
        historyDoc.append("billNo", billNo);
        historyDoc.append("source", source);
        historyDoc.append("userId", userId);
        historyDoc.append("userName", name);
        historyDoc.append("data", prdReturnOrderDoc);
        historyDoc.append("event", "prdReturn");
        historyDoc.append("filteredDetails", validDetails);
        try {
            syncInnerReturnBn(historyDoc, returnTime);
            historyDoc.append("success", true);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                historyDoc.remove("message");
                historyDoc.append("updateUserId", userId);
                historyDoc.append("updateUserName", name);
                syncOrderDao.updateById(id, historyDoc);
            }
        } catch (Exception e) {
            historyDoc.append("prdReturnOrder", false).append("message", e.getMessage()).append("success", false);
            if (id == null) {
                syncOrderDao.insertOne(historyDoc);
            } else {
                historyDoc.remove("_id");
                historyDoc.remove("createTime");
                historyDoc.remove("updateTime");
                syncOrderDao.updateById(id, historyDoc);
            }
            throw e;
        }
    }

    /**
     * 其他入库合拆箱传批号调整单
     *
     * @param userId
     * @param name
     * @param otherInBillNo
     * @param otherOutBillNo
     * @param source
     * @throws Exception
     */
    @Override
    public void syncTransferDirectOther(ObjectId userId, String name, String otherInBillNo, String otherOutBillNo, String source) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        Iterator<Document> otherOutItr = otherOutDetailDao.findList(Criteria.where("billNo").is(otherOutBillNo), null, 0, 0);

        Document otherInDoc = otherInDetailDao.findOne(Criteria.where("billNo").is(otherInBillNo));
        String toStockNo = VtuzxUtil.getString(otherInDoc, "stockNo");//调入仓库编号
        String updateBatchNo = VtuzxUtil.getString(otherInDoc, "batchNo");//调整后的批次号
        Date toCreateTime = VtuzxUtil.getObject(otherInDoc, "createTime");//调入日期
        String time = VtuzxUtil.formatYmdHmsF(toCreateTime);

//        Boolean aBoolean = otherService.otherMaterial(otherInBillNo, otherOutBillNo);
        List<Document> otherOutList = new ArrayList<>();
        while (otherOutItr.hasNext()) {
            Document otherOutDoc = otherOutItr.next();
            otherOutList.add(otherOutDoc);
        }
        Map<String, Object> batchParam = new HashMap<>();//传单param
        Map<String, Object> batchModel = new HashMap<>();//单据头
        List<Map<String, Object>> batchList = new ArrayList<>();//单据体
        int groupNum = 1;//但具体分组字段
        for (Document otherOutDoc : otherOutList) {
            String batchNo = VtuzxUtil.getString(otherOutDoc, "batchNo");
            String unitName = VtuzxUtil.getString(otherOutDoc, "unit");
            String materialNo = VtuzxUtil.getString(otherOutDoc, "materialNo");
            double count = VtuzxUtil.getDouble(otherOutDoc, "count");
            String stockNo = VtuzxUtil.getString(otherOutDoc, "stockNo");

            //判断转换前后的批号是否相同，相同的不用传
            if (!batchNo.equals(updateBatchNo)) {
                //判断单位是汉字还是拼音
                Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
                Matcher m = p.matcher(unitName);
                String unit = "";
                if (!m.find()) {//不是汉字
                    //查询单位编码，直接传文字无效
                    unit = unitName;
                } else {//如果是汉字
                    String cond = String.format("FName = '%s'", unitName);
                    List<VtuzxMap> bd_customer = kingdeeService.query(client, "BD_UNIT", new VtuzxArrayList<>(
                            "FNumber",//单位编码
                            "FNAME"//单位名称
                    ), cond);

                    if (bd_customer != null && bd_customer.size() > 0) {
                        unit = bd_customer.get(0).getString("FNumber");
                    }
                }


                //转换前
                Map<String, Object> batchEntry = new LinkedHashMap<>();
                batchEntry.put("FGroup", groupNum);
                batchEntry.put("FConvertType", "A");//转换类型
                batchEntry.put("FMATERIALID", new Document("FNumber", materialNo));//物料
                batchEntry.put("FLot", new Document("FNumber", batchNo));//批号
                batchEntry.put("FUnitID", new Document("FNumber", unit));//单位
                batchEntry.put("FQty", count);//转换数量
                batchEntry.put("FSTOCKID", new Document("FNumber", stockNo));//仓库
                batchEntry.put("FStockStatusId", new Document("FNumber", "KCZT01_SYS"));//库存状态
                batchEntry.put("FKeeperTypeId", "BD_KeeperOrg");//保管者类型
                batchEntry.put("FKeeperId", new Document("FNumber", "100"));//保管者
                batchEntry.put("FOwnerTypeId", "BD_OwnerOrg");//货主类型
                batchEntry.put("FOwnerId", new Document("FNumber", "100"));//货主
                batchList.add(batchEntry);

                //转换后
                Map<String, Object> afterEntry = new LinkedHashMap<>();
                afterEntry.put("FGroup", groupNum);
                afterEntry.put("FConvertType", "B");//转换类型
                afterEntry.put("FMATERIALID", new Document("FNumber", materialNo));//物料
                afterEntry.put("FLot", new Document("FNumber", updateBatchNo));//批号
                afterEntry.put("FUnitID", new Document("FNumber", unit));//单位
                afterEntry.put("FQty", count);//转换数量
                afterEntry.put("FSTOCKID", new Document("FNumber", toStockNo));//仓库
                afterEntry.put("FStockStatusId", new Document("FNumber", "KCZT01_SYS"));//库存状态
                afterEntry.put("FKeeperTypeId", "BD_KeeperOrg");//保管者类型
                afterEntry.put("FKeeperId", new Document("FNumber", "100"));//保管者
                afterEntry.put("FOwnerTypeId", "BD_OwnerOrg");//货主类型
                afterEntry.put("FOwnerId", new Document("FNumber", "100"));//货主
                batchList.add(afterEntry);
                groupNum++;
            }

        }

        batchModel.put("FID", 0);//实体主键
        batchModel.put("FBillTypeID", new Document("FNUMBER", "PHTZ01_SYS"));//单据类型
        batchModel.put("FStockOrgId", new Document("FNumber", "100"));//库存组织
        batchModel.put("FDate", time);//单据日期
        batchModel.put("FOwnerTypeIdHead", "BD_OwnerOrg");//货主类型
        batchModel.put("FOwnerIdHead", new Document("FNumber", "100"));
        batchModel.put("F_ora_ZTDJH ", otherInBillNo);//中台单据号
        batchModel.put("FSTK_LOTADJUSTENTRY", batchList);
        batchParam.put("NeedUpDateFields", new ArrayList<>());
        batchParam.put("NeedReturnFields", new ArrayList<>());
        batchParam.put("IsDeleteEntry", true);
        batchParam.put("SubSystemId", "");
        batchParam.put("IsVerifyBaseDataField", false);
        batchParam.put("IsEntryBatchFill", true);
        batchParam.put("ValidateFlag", true);
        batchParam.put("NumberSearch", true);
        batchParam.put("InterationFlags", "");
        batchParam.put("Model", batchModel);

        try {
            List<VtuzxMap> inStockList = kingdeeService.save(client, "STK_LOTADJUST", batchParam);
            VtuzxMap prdInMap = inStockList.get(0);
            String inNumber = VtuzxUtil.getString(prdInMap, "Number");
            kingdeeService.submit(client, "STK_LOTADJUST", "0", inNumber);
            kingdeeService.audit(client, "STK_LOTADJUST", "0", inNumber, "STK_InvCheckResult");
        } catch (Exception e) {
            _logger.info(e.getMessage());
        }
    }

    @Override
    public void syncPurOrderReturn(ObjectId userId, String name, String billNo, String source) throws Exception {
        Iterator<Document> purReturnItr = purReturnDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        Document purReturn = purReturnDao.findOne(Criteria.where("billNo").is(billNo));
        String createTime = VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(purReturn, "createTime"));
        String supplierNo = VtuzxUtil.getString(purReturn, "supplierNo");
        String prdInBillNo = VtuzxUtil.getString(purReturn, "prdInBillNo");

        List<Document> purReturnList = new ArrayList<>();
        while (purReturnItr.hasNext()) {
            Document purReturnDoc = purReturnItr.next();
            purReturnList.add(purReturnDoc);
        }
        //金蝶token
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        Map<String, Object> purParam = new LinkedHashMap<>();//传单param
        Map<String, Object> purModel = new LinkedHashMap<>();//单据头

        String supplier = "";
        //查询金蝶供应商编码
        if (!supplierNo.startsWith("0")) {
            List<VtuzxMap> supplierQuery = kingdeeService.query(client, "BD_Supplier", new VtuzxArrayList<>(
                            "Fnumber_Y",
                            "FNumber"
                    ),
                    String.format("Fnumber_Y = '%s'", supplierNo), null, 0, 1);
            if (VtuzxUtil.isEmpty(supplierQuery)) {
                throw new VtuzxException(String.format("供应商[%s]在金蝶中不存在", supplierNo));
            }
            supplier = VtuzxUtil.getString(supplierQuery.get(0), "FNumber");
        } else {
            supplier = supplierNo;
        }

        //添加单据头信息
        purModel.put("FID", 0);
        purModel.put("FBillTypeId", new Document("FNUMBER", "TLD01_SYS"));
        purModel.put("FDate", createTime);
        purModel.put("FMRTYPE", "B");//退料类型
        purModel.put("FMRMODE", "A");//退料方式
        purModel.put("FStockOrgId", new Document("FNumber", "100"));//退料组织
        purModel.put("FRequireOrgId", new Document("FNumber", "100"));
        purModel.put("FPurchaseOrgId", new Document("FNumber", "100"));
        purModel.put("FSupplierID", new Document("FNumber", supplier));//供应商
        purModel.put("FACCEPTORID", new Document("FNumber", supplier));//接收方
        purModel.put("FSettleId", new Document("FNumber", supplier));//结算方
        purModel.put("FCHARGEID", new Document("FNumber", supplier));//收款方
        purModel.put("FOwnerTypeIdHead", "BD_OwnerOrg");//货主类型
        purModel.put("FOwnerIdHead", new Document("FNumber", "100"));//货主
        purModel.put("F_ora_ZTDJH", billNo);//中台单据号

        Map<String, Object> purmrbfin = new LinkedHashMap<>();//财务信息
        purmrbfin.put("FSettleOrgId", new Document("FNumber", "100"));//结算组织
        purmrbfin.put("FSettleCurrId", new Document("FNumber", "PRE001"));//结算币别
        purmrbfin.put("FIsIncludedTax", true);
        purmrbfin.put("FPRICETIMEPOINT", "1");
        purmrbfin.put("FLOCALCURRID", new Document("FNumber", "PRE001"));//本位币
        purmrbfin.put("FEXCHANGETYPEID", new Document("FNumber", "HLTX01_SYS"));//汇率类型
        purmrbfin.put("FEXCHANGERATE", 1);//汇率
        purmrbfin.put("FISPRICEEXCLUDETAX", true);//价外税

        purModel.put("FPURMRBFIN", purmrbfin);

        List<Map<String, Object>> FPURMRBENTRY = new ArrayList<>();//明细信息
        //添加明细信息
        for (Document data : purReturnList) {
            String materialNo = VtuzxUtil.getString(data, "materialNo");
            String materialSpec = VtuzxUtil.getString(data, "materialSpec");
            String unit = VtuzxUtil.getString(data, "unit");
            double count = VtuzxUtil.getDouble(data, "returnCount");
            String stockNo = VtuzxUtil.getString(data, "stockNo");

            Map<String, Object> entryMap = new LinkedHashMap<>();
            entryMap.put("FRowType", "Standard");
            entryMap.put("FMATERIALID", new Document("FNumber", materialNo));
//            entryMap.put("FMaterialDesc",new Document("FNumber",materialSpec));
            entryMap.put("FUnitID", new Document("FNumber", unit));
            entryMap.put("FRMREALQTY", count);//实退数量
            entryMap.put("FREPLENISHQTY", count);//补料数量
            entryMap.put("FKEAPAMTQTY", count);//扣款数量
            entryMap.put("FPRICEUNITID", new Document("FNumber", unit));
            entryMap.put("FSTOCKID", new Document("FNumber", stockNo));
            entryMap.put("FStockStatusId", new Document("FNumber", "KCZT01_SYS"));//库存状态
            entryMap.put("FIsReceiveUpdateStock", false);
            entryMap.put("FGiveAway", false);
            entryMap.put("FPriceBaseQty", count);//扣款数量
            entryMap.put("FCarryUnitId", new Document("FNumber", unit));
            entryMap.put("FCarryQty", count);
            entryMap.put("FCarryBaseQty", count);
            entryMap.put("FBILLINGCLOSE", false);//立账关闭
            entryMap.put("FOWNERTYPEID", "BD_OwnerOrg");
            entryMap.put("FOWNERID", new Document("FNumber", "100"));
            entryMap.put("FENTRYTAXRATE", 13);
            entryMap.put("FIsStock", false);
            String FId = "";//原单内码
            String FEntryId = "";//分录内码
            //查询原单内码和分录内码
            List<VtuzxMap> prdInQuery = kingdeeService.query(client, "STK_InStock", new VtuzxArrayList<>(
                            "FId",
                            "FInStockEntry_FEntryID"
                    ),
                    String.format("F_ora_ZTDJH = '%s' and FMaterialId.FNumber = '%s'", prdInBillNo, materialNo), null, 0, 1);
            if (!VtuzxUtil.isEmpty(prdInQuery)) {
                FId = VtuzxUtil.getString(prdInQuery.get(0), "FId");
                FEntryId = VtuzxUtil.getString(prdInQuery.get(0), "FInStockEntry_FEntryID");
            }

            //添加link信息(和采购入库单关联)
            List<Map<String, Object>> linkList = new ArrayList<>();
            Map<String, Object> linkMap = new LinkedHashMap<>();
            linkMap.put("FPURMRBENTRY_Link_FRuleId", "STK_InStock-pur_MRB");//下推规则
            linkMap.put("FPURMRBENTRY_Link_FSTableName", "T_STK_INSTOCKENTRY");//关联表名
            linkMap.put("FPURMRBENTRY_Link_FSBillId", FId);//源单内码
            linkMap.put("FPURMRBENTRY_Link_FSId", FEntryId);// 源单分录内码
            linkList.add(linkMap);
            entryMap.put("FPURMRBENTRY_Link", linkList);
            FPURMRBENTRY.add(entryMap);
        }
        purModel.put("FPURMRBENTRY", FPURMRBENTRY);

        purParam.put("NeedUpDateFields", new ArrayList<>());
        purParam.put("NeedReturnFields", new ArrayList<>());
        purParam.put("IsDeleteEntry", true);
        purParam.put("SubSystemId", "");
        purParam.put("IsVerifyBaseDataField", false);
        purParam.put("IsEntryBatchFill", true);
        purParam.put("ValidateFlag", true);
        purParam.put("NumberSearch", true);
        purParam.put("InterationFlags", "");
        purParam.put("Model", purModel);

        try {
            List<VtuzxMap> purReturnBillList = kingdeeService.save(client, "PUR_MRB", purParam);
            VtuzxMap prdReturnMap = purReturnBillList.get(0);
            String number = VtuzxUtil.getString(prdReturnMap, "Number");
            kingdeeService.submit(client, "PUR_MRB", "0", number);
            kingdeeService.audit(client, "PUR_MRB", "0", number, "STK_InvCheckResult");
        } catch (Exception e) {
            _logger.info(e.getMessage());
        }
    }

    @Override
    public VtuzxDownloadBean downloadSyncOrderHistory(VtuzxToken token, Map<String, Object> param) throws Exception {
        Criteria cond = new Criteria();
        String billNo = VtuzxUtil.getString(param, "billNo");
        String event = VtuzxUtil.getString(param, "event");
        String userName = VtuzxUtil.getString(param, "userName");

        List<String> updateTime = VtuzxUtil.getObject(param, "updateTime");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");

        if (!VtuzxUtil.isEmpty(userName)) {
            cond.and("userName").regex(userName);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }
        if (!VtuzxUtil.isEmpty(event)) {
            cond.and("event").regex(event);
        }
        if (!VtuzxUtil.isEmpty(updateTime)) {
            cond.and("updateTime").gte(VtuzxUtil.parseDate(updateTime.get(0))).lte(VtuzxUtil.parseDate(updateTime.get(1) + " 23:59:59"));
        }
        VtuzxPage page = syncOrderDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("event", VtuzxUtil.getString(doc, "event"))
                .append("updateUserName", VtuzxUtil.getString(doc, "updateUserName"))
                .append("userName", VtuzxUtil.getString(doc, "userName"))
                .append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "createTime")))
                .append("updateTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "updateTime")))
                .append("data", VtuzxUtil.getObject(doc, "data"))
                .append("detailData", VtuzxUtil.getObject(doc, "detailData"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName"))
                .append("createUserId", VtuzxUtil.getString(doc, "createUserId"))
                .append("success", VtuzxUtil.getBoolean(doc, "success"))
                .append("param", VtuzxUtil.getObject(doc, "param"))
                .append("message", VtuzxUtil.getString(doc, "message"))
                .append("kingdeeNumber", VtuzxUtil.getString(doc, "kingdeeNumber")));

        String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

        List<VtuzxExcelSheet> sheets = new ArrayList<>();
        VtuzxExcelSheet sheet0 = new VtuzxExcelSheet(0, "订单同步");
        int col = 0;
        int row = 0;
        VtuzxExcelRow header0 = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                new VtuzxExcelCell(col++, "订单编号"),
                new VtuzxExcelCell(col++, "同步类型"),
                new VtuzxExcelCell(col++, "同步状态"),
                new VtuzxExcelCell(col++, "同步人"),
                new VtuzxExcelCell(col++, "金蝶单号"),
                new VtuzxExcelCell(col++, "错误信息"),
                new VtuzxExcelCell(col++, "同步时间")

        ));
        sheet0.addRow(header0);

        for (VtuzxMap detail : dataList) {
//            VtuzxMap header = VtuzxUtil.getObject(detail, "header");
//            List<VtuzxMap> boxList = VtuzxUtil.getObject(detail, "boxList");

            col = 0;
            VtuzxExcelRow dataRow = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "billNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "event")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getBoolean(detail, "success") ? "成功" : "失败"),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "userName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "kingdeeNumber")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "message")),
                    new VtuzxExcelCell(col, VtuzxUtil.getString(detail, "updateTime"))
            ));
            sheet0.addRow(dataRow);
        }

        sheet0.setColumnWidth(new VtuzxArrayList<>(
                new int[]{0, 200},
                new int[]{1, 200},
                new int[]{2, 200},
                new int[]{3, 100},
                new int[]{4, 200},
                new int[]{5, 200},
                new int[]{6, 200}
        ));

        sheets.add(sheet0);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        VtuzxExcel.write(stream, sheets);
        return new VtuzxDownloadBean("订单同步" + timestamp + ".xlsx", stream);

    }

    @Override
    public VtuzxMap getSync(ObjectId userId, String name, Map<String, Object> param) {
        Criteria cond = new Criteria();
        String billNo = VtuzxUtil.getString(param, "billNo");
        String createUserName = VtuzxUtil.getString(param, "createUserName");
        List<String> startTime = VtuzxUtil.getObject(param, "startTime");
        int pageSize = VtuzxUtil.getInt(param, "pageSize");
        int pageIndex = VtuzxUtil.getInt(param, "pageIndex");

        if (!VtuzxUtil.isEmpty(createUserName)) {
            cond.and("createUserName").regex(createUserName);
        }
        if (!VtuzxUtil.isEmpty(billNo)) {
            cond.and("billNo").regex(billNo);
        }

        if (!VtuzxUtil.isEmpty(startTime)) {
            cond.and("startTime").gte(VtuzxUtil.parseDate(startTime.get(0))).lte(VtuzxUtil.parseDate(startTime.get(1) + " 23:59:59"));
        }

        VtuzxPage page = syncDao.page(cond, new Document("createTime", -1), pageIndex, pageSize);
        List<VtuzxMap> dataList = page.iterator(doc -> new VtuzxMap("id", VtuzxUtil.getString(doc, IVtuzxConst.Key__id))
                .append("billNo", VtuzxUtil.getString(doc, "billNo"))
                .append("startTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "startTime")))
                .append("endTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(doc, "endTime")))
                .append("successCount", VtuzxUtil.getInt(doc, "successCount"))
                .append("sumCount", VtuzxUtil.getInt(doc, "sumCount"))
                .append("falseCount", VtuzxUtil.getInt(doc, "falseCount"))
                .append("createUserName", VtuzxUtil.getString(doc, "createUserName")));
        return new VtuzxMap(IVtuzxConst.Key_total, page.total()).append(IVtuzxConst.Key_data, dataList);
    }

    @Override
    public VtuzxDownloadBean downloadSyncHistory(VtuzxToken token, Map<String, Object> param) throws Exception {
        String billNo = VtuzxUtil.getString(param, "billNo");
        Iterator<Document> syncOrderItr = syncOrderDao.findList(Criteria.where("syncBillNo").is(billNo), null, 0, 0);
        List<Document> dataList = new ArrayList<>();
        while (syncOrderItr.hasNext()) {
            Document syncOrderDoc = syncOrderItr.next();
            syncOrderDoc.append("createTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(syncOrderDoc, "createTime")))
                    .append("updateTime", VtuzxUtil.formatYmdHmsF(VtuzxUtil.getObject(syncOrderDoc, "updateTime")));
            dataList.add(syncOrderDoc);
        }
        String timestamp = new SimpleDateFormat("yyMMddHHmmss").format(new Date());

        List<VtuzxExcelSheet> sheets = new ArrayList<>();
        VtuzxExcelSheet sheet0 = new VtuzxExcelSheet(0, "订单同步");
        int col = 0;
        int row = 0;
        VtuzxExcelRow header0 = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                new VtuzxExcelCell(col++, "订单编号"),
                new VtuzxExcelCell(col++, "同步类型"),
                new VtuzxExcelCell(col++, "同步状态"),
                new VtuzxExcelCell(col++, "同步人"),
                new VtuzxExcelCell(col++, "金蝶单号"),
                new VtuzxExcelCell(col++, "错误信息"),
                new VtuzxExcelCell(col++, "同步时间")

        ));
        sheet0.addRow(header0);

        for (Document detail : dataList) {
//            VtuzxMap header = VtuzxUtil.getObject(detail, "header");
//            List<VtuzxMap> boxList = VtuzxUtil.getObject(detail, "boxList");

            col = 0;
            VtuzxExcelRow dataRow = new VtuzxExcelRow(row++, new VtuzxArrayList<>(
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "billNo")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "event")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getBoolean(detail, "success") ? "成功" : "失败"),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "userName")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "kingdeeNumber")),
                    new VtuzxExcelCell(col++, VtuzxUtil.getString(detail, "message")),
                    new VtuzxExcelCell(col, VtuzxUtil.getString(detail, "updateTime"))
            ));
            sheet0.addRow(dataRow);
        }

        sheet0.setColumnWidth(new VtuzxArrayList<>(
                new int[]{0, 200},
                new int[]{1, 200},
                new int[]{2, 200},
                new int[]{3, 100},
                new int[]{4, 200},
                new int[]{5, 200},
                new int[]{6, 200}
        ));

        sheets.add(sheet0);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        VtuzxExcel.write(stream, sheets);
        return new VtuzxDownloadBean("订单同步" + timestamp + ".xlsx", stream);
    }

    private void syncInnerReturn(Document historyDoc, String returnTime) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
        Document data = VtuzxUtil.getObject(historyDoc, "data");
        String createUserName = VtuzxUtil.getString(data, "createUserName");
        String taskBillNo = VtuzxUtil.getString(data, "taskBillNo");
        String createTime = VtuzxUtil.formatYmdF(VtuzxUtil.getObject(data, "createTime"));
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");

        //任务单号查询生产订单
        List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                        "FBillNo",
                        "FQty"
                ),
                String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 1);

        if (VtuzxUtil.isEmpty(prdOrderQuery)) {
            throw new VtuzxException(String.format("金蝶不存在中台单据号为[%s]的生产订单", taskBillNo));
        }
        String kingdeeBillNo = VtuzxUtil.getString(prdOrderQuery.get(0), "FBillNo");

        //生产订单号查询用料清单
        List<VtuzxMap> materialBomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                        "FID",
                        "FBillNo",
                        "FMOBillNO",
                        "FMaterialID2.FNumber",
                        "FUnitID2.FNumber",
                        "FNeedQty2",
                        "FEntity_FEntryID"
                ),
                String.format("FMOBillNO = '%s'", kingdeeBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialBomQuery)) return;
        String fBillNo = VtuzxUtil.getString(materialBomQuery.get(0), "FBillNo");


        //用料清单下推生产退料
        List<String> bomNumberList = new ArrayList<>();
        bomNumberList.add(fBillNo);
        Map<String, Object> bomToPickMap = new LinkedHashMap<>();
        bomToPickMap.put("Ids", "");
        bomToPickMap.put("Numbers", bomNumberList);
        bomToPickMap.put("EntryIds", "");
        bomToPickMap.put("RuleId", "ora_PRD_PPBOM2RETURNMTRL_ZY");
        bomToPickMap.put("TargetBillTypeId", "");
        bomToPickMap.put("TargetOrgId", 0);
        bomToPickMap.put("TargetFormId", "");
        bomToPickMap.put("IsEnableDefaultRule", false);
        bomToPickMap.put("IsDraftWhenSaveFail", true);
        bomToPickMap.put("CustomParams", new VtuzxMap());

        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        param.append("PRD_PPBOM", bomToPickMap);
        List<VtuzxMap> returnBillList = kingdeeService.push(client, "PRD_PPBOM", bomToPickMap);
        VtuzxMap returnBillMap = returnBillList.get(0);
        String kingdeeReturnBillNo = VtuzxUtil.getString(returnBillMap, "Number");
        int kingdeeReturnFid = VtuzxUtil.getInt(returnBillMap, "Id");

        //生产退料单号查询退料单
        List<VtuzxMap> retuenOrderQuery = kingdeeService.query(client, "PRD_ReturnMtrl", new VtuzxArrayList<>(
                        "FID",
                        "FEntity_FEntryID",
                        "FMaterialId.FNumber",
                        "FLot.FNumber",
                        "FQty"
                ),
                String.format("FId = '%d'", kingdeeReturnFid), null, 0, 0);

        if (VtuzxUtil.isEmpty(retuenOrderQuery)) return;
        String fid = VtuzxUtil.getString(retuenOrderQuery.get(0), "FID");
        Map<String, Object> returnOrderMap = new HashMap<>();//k:物料加批次，k:document
        //领料和补料批次和物料相同的情况下，退料会退多个,先筛选一下退料
//        for (VtuzxMap returnMap : retuenOrderQuery){
//            String fMaterialNo = VtuzxUtil.getString(returnMap, "FMaterialId.FNumber");
//            String fFlot = VtuzxUtil.getString(returnMap, "FLot.FNumber");
//            double FQty = VtuzxUtil.getDouble(returnMap,"FQty");
//
//            if (FQty > 0){
//                VtuzxMap returnDoc = (VtuzxMap) returnOrderMap.get(fMaterialNo + "_" + fFlot);
//                if (VtuzxUtil.isEmpty(returnDoc) ){
//                    returnOrderMap.put(fMaterialNo + "_" + fFlot,returnMap);
//                } else {
//                    double returnQty = VtuzxUtil.getDouble(returnDoc,"FQty");
//                    returnDoc.replace("FQty",returnQty + FQty);
//                    returnOrderMap.put(fMaterialNo + "_" + fFlot,returnDoc);
//                }
//            }
//
//        }

        Map<String, Object> prdReturnOrderParam = new LinkedHashMap<>();
        Map<String, Object> prdReturnOrderModel = new LinkedHashMap<>();

        List<Document> returnOrderList = new ArrayList<>();
        Iterator<Document> prdReturnOrderItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (prdReturnOrderItr.hasNext()) {
            Document prdReturnOrderDoc = prdReturnOrderItr.next();
            returnOrderList.add(prdReturnOrderDoc);
        }

        List<VtuzxMap> newReturnOrderQuery = new ArrayList<>();
        for (Map.Entry entry : returnOrderMap.entrySet()) {
            VtuzxMap returnDoc = (VtuzxMap) entry.getValue();
            newReturnOrderQuery.add(returnDoc);
        }
        List<Map<String, Object>> fReturnEntry = new ArrayList<>();
        xunhuan:
//循环别名
        for (VtuzxMap returnOrder : retuenOrderQuery) {
            Map<String, Object> returnMap = new LinkedHashMap<>();
            String fEntity_FEntryID = VtuzxUtil.getString(returnOrder, "FEntity_FEntryID");
            String fMaterialNo = VtuzxUtil.getString(returnOrder, "FMaterialId.FNumber");
            String fFlot = VtuzxUtil.getString(returnOrder, "FLot.FNumber");
            double FQty = VtuzxUtil.getDouble(returnOrder, "FQty");
            for (Document returnOrderDoc : returnOrderList) {
                String materialNo = VtuzxUtil.getString(returnOrderDoc, "materialNo");
                String stockNo = VtuzxUtil.getString(returnOrderDoc, "stockNo");
                String batchNo = VtuzxUtil.getString(returnOrderDoc, "batchNo");
                double count = VtuzxUtil.getDouble(returnOrderDoc, "count");
//                if (count == 0) {
//                    continue;
//                }
                //存新分录
                if (fMaterialNo.equals(materialNo) && fFlot.equals(batchNo)) {
                    //判断够不够扣
                    if (FQty >= count) {
                        returnMap.put("FEntryID", fEntity_FEntryID);
                        returnMap.put("FAPPQty", count);
                        returnMap.put("FQty", count);
                        returnMap.put("FReturnType", "1");
                        returnMap.put("FStockId", new VtuzxMap("FNumber", stockNo));
                        returnMap.put("FLot", new VtuzxMap("FNumber", batchNo));
                        returnMap.put("FReserveType", "1");
                        returnMap.put("FBASESTOCKQTY", count);
                        returnMap.put("FStockAppQty", count);
                        returnMap.put("FStockQty", count);
                        returnMap.put("FBaseAppQty", count);
                        returnMap.put("FBaseQty", count);
                        fReturnEntry.add(returnMap);
                        returnOrderDoc.replace("count", 0);
                        if (fReturnEntry.size() == returnOrderList.size()) {
                            break xunhuan;
                        }

                    } else {
                        returnMap.put("FEntryID", fEntity_FEntryID);
                        returnMap.put("FAPPQty", FQty);
                        returnMap.put("FQty", FQty);
                        returnMap.put("FReturnType", "1");
                        returnMap.put("FStockId", new VtuzxMap("FNumber", stockNo));
                        returnMap.put("FLot", new VtuzxMap("FNumber", batchNo));
                        returnMap.put("FReserveType", "1");
                        returnMap.put("FBASESTOCKQTY", FQty);
                        returnMap.put("FStockAppQty", FQty);
                        returnMap.put("FStockQty", FQty);
                        returnMap.put("FBaseAppQty", FQty);
                        returnMap.put("FBaseQty", FQty);
                        fReturnEntry.add(returnMap);
                        returnOrderDoc.replace("count", count - FQty);
                    }

                }
            }
        }

        prdReturnOrderModel.put("FID", fid);
        if (!VtuzxUtil.isEmpty(returnTime) && !"Invalid Date".equals(returnTime)) {
            prdReturnOrderModel.put("FDate", returnTime);
        } else {
            prdReturnOrderModel.put("FDate", createTime);
        }

        prdReturnOrderModel.put("F_sctld_ZTTLR", createUserName);
        prdReturnOrderModel.put("F_sctld_ZTDJH", billNo);
        prdReturnOrderModel.put("F_sctld_SJLY", source);
        prdReturnOrderModel.put("F_sctld_ZTTLSJ ", createTime);
        prdReturnOrderModel.put("FEntity", fReturnEntry);

        prdReturnOrderParam.put("NeedUpDateFields", new ArrayList<>());
        prdReturnOrderParam.put("NeedReturnFields", new ArrayList<>());
        prdReturnOrderParam.put("IsDeleteEntry", true);
        prdReturnOrderParam.put("SubSystemId", "");
        prdReturnOrderParam.put("IsVerifyBaseDataField", false);
        prdReturnOrderParam.put("IsEntryBatchFill", true);
        prdReturnOrderParam.put("ValidateFlag", true);
        prdReturnOrderParam.put("NumberSearch", true);
        prdReturnOrderParam.put("InterationFlags", "");
        prdReturnOrderParam.put("Model", prdReturnOrderModel);

        param.append("PRD_ReturnMtrl", prdReturnOrderParam);
        try {
            List<VtuzxMap> prdReturnBillList = kingdeeService.save(client, "PRD_ReturnMtrl", prdReturnOrderParam);
            VtuzxMap prdReturnMap = prdReturnBillList.get(0);
            String number = VtuzxUtil.getString(prdReturnMap, "Number");
            kingdeeService.submit(client, "PRD_ReturnMtrl", "0", number);
            kingdeeService.audit(client, "PRD_ReturnMtrl", "0", number, "STK_InvCheckResult");
            historyDoc.append("kingdeeNumber", number);
            historyDoc.append("prdReturnOrder", true);
        } catch (Exception e) {
            _logger.info(e.getMessage());
        }

    }

    private void syncInnerReturnBn(Document historyDoc, String returnTime) throws Exception {
        VtuzxKingdeeCloudClient client = kingdeeService.loginKingdeeYX();
        Document data = VtuzxUtil.getObject(historyDoc, "data");
        String createUserName = VtuzxUtil.getString(data, "createUserName");
        String taskBillNo = VtuzxUtil.getString(data, "taskBillNo");
        String createTime = VtuzxUtil.formatYmdF(VtuzxUtil.getObject(data, "createTime"));
        String billNo = VtuzxUtil.getString(historyDoc, "billNo");
        String source = VtuzxUtil.getString(historyDoc, "source");
        //任务单号查询生产订单
        List<VtuzxMap> prdOrderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
                        "FBillNo",
                        "FQty"
                ),
                String.format("F_scdd_ZTDJH = '%s'", taskBillNo), null, 0, 1);
        if (VtuzxUtil.isEmpty(prdOrderQuery)) {
            throw new VtuzxException(String.format("金蝶不存在中台单据号为[%s]的生产订单", taskBillNo));
        }
        String kingdeeBillNo = VtuzxUtil.getString(prdOrderQuery.get(0), "FBillNo");
        //生产订单号查询用料清单
        List<VtuzxMap> materialBomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
                        "FID",
                        "FBillNo",
                        "FMOBillNO",
                        "FMaterialID2.FNumber",
                        "FUnitID2.FNumber",
                        "FNeedQty2",
                        "FEntity_FEntryID"
                ),
                String.format("FMOBillNO = '%s'", kingdeeBillNo), null, 0, 0);
        if (VtuzxUtil.isEmpty(materialBomQuery)) return;
        String fBillNo = VtuzxUtil.getString(materialBomQuery.get(0), "FBillNo");
        //用料清单下推生产退料
        List<String> bomNumberList = new ArrayList<>();
        bomNumberList.add(fBillNo);
        Map<String, Object> bomToPickMap = new LinkedHashMap<>();
        bomToPickMap.put("Ids", "");
        bomToPickMap.put("Numbers", bomNumberList);
        bomToPickMap.put("EntryIds", "");
        bomToPickMap.put("RuleId", VtuzxUtil.getString(prdPushRuleDao.findOne(Criteria
                .where("ruleName").is("PPBOMPushReturnMtrl")
                .and("ruleType").is("product")
                .and("tokenType").is("kingdee3")
        ), "ruleId"));
        bomToPickMap.put("TargetBillTypeId", "");
        bomToPickMap.put("TargetOrgId", 0);
        bomToPickMap.put("TargetFormId", "");
        bomToPickMap.put("IsEnableDefaultRule", false);
        bomToPickMap.put("IsDraftWhenSaveFail", true);
        bomToPickMap.put("CustomParams", new VtuzxMap());
        historyDoc.append("param", new VtuzxMap());
        VtuzxMap param = VtuzxUtil.getObject(historyDoc, "param");
        param.append("PRD_PPBOM", bomToPickMap);
        List<VtuzxMap> returnBillList = kingdeeService.push(client, "PRD_PPBOM", bomToPickMap);
        VtuzxMap returnBillMap = returnBillList.get(0);
        String kingdeeReturnBillNo = VtuzxUtil.getString(returnBillMap, "Number");
        int kingdeeReturnFid = VtuzxUtil.getInt(returnBillMap, "Id");
        // 生产退料单号查询退料单
        List<VtuzxMap> retuenOrderQuery = kingdeeService.query(client, "PRD_ReturnMtrl", new VtuzxArrayList<>(
                        "FID",
                        "FEntity_FEntryID",
                        "FMaterialId.FNumber",
                        "FLot.FNumber",
                        "FQty"
                ),
                String.format("FId = '%d'", kingdeeReturnFid), null, 0, 0);
        if (VtuzxUtil.isEmpty(retuenOrderQuery)) return;
        String fid = VtuzxUtil.getString(retuenOrderQuery.get(0), "FID");
        //获取中台退料明细数据
        /*List<Document> returnOrderList = new ArrayList<>();
        Iterator<Document> prdReturnOrderItr = prdInDetailDao.findList(Criteria.where("billNo").is(billNo), null, 0, 0);
        while (prdReturnOrderItr.hasNext()) {
            Document prdReturnOrderDoc = prdReturnOrderItr.next();
            returnOrderList.add(prdReturnOrderDoc);
        }*/
        List<Document> validDetails = VtuzxUtil.getObject(historyDoc, "filteredDetails");
        List<Document> returnOrderList = new ArrayList<>(validDetails);
        //构建退料明细的Map，key为materialNo_batchNo，value为退料明细列表
        Map<String, List<Document>> returnOrderMap = new HashMap<>();
        for (Document returnOrderDoc : returnOrderList) {
            String materialNo = VtuzxUtil.getString(returnOrderDoc, "materialNo");
            String batchNo = VtuzxUtil.getString(returnOrderDoc, "batchNo");
            String key = materialNo + "_" + batchNo;
            if (!returnOrderMap.containsKey(key)) {
                returnOrderMap.put(key, new ArrayList<>());
            }
            returnOrderMap.get(key).add(returnOrderDoc);
        }
        List<Map<String, Object>> fReturnEntry = new ArrayList<>();
        //处理金蝶返回的每条退料分录
        for (VtuzxMap returnOrder : retuenOrderQuery) {
            Map<String, Object> returnMap = new LinkedHashMap<>();
            String fEntity_FEntryID = VtuzxUtil.getString(returnOrder, "FEntity_FEntryID");
            String fMaterialNo = VtuzxUtil.getString(returnOrder, "FMaterialId.FNumber");
            String fFlot = VtuzxUtil.getString(returnOrder, "FLot.FNumber");
            double FQty = VtuzxUtil.getDouble(returnOrder, "FQty");
            String key = fMaterialNo + "_" + fFlot;
            List<Document> matchingReturnOrders = returnOrderMap.get(key);
            if (matchingReturnOrders != null && !matchingReturnOrders.isEmpty()) {
                //计算该物料批次的总退料数量
                double totalCount = 0;
                String stockNo = VtuzxUtil.getString(matchingReturnOrders.get(0), "stockNo"); //取第一个明细的仓库
                for (Document returnOrderDoc : matchingReturnOrders) {
                    double count = VtuzxUtil.getDouble(returnOrderDoc, "count");
                    totalCount += count;
                }
                if (totalCount > 0) {
                    returnMap.put("FEntryID", fEntity_FEntryID);
                    returnMap.put("FAPPQty", totalCount);
                    returnMap.put("FQty", totalCount);
                    returnMap.put("FReturnType", "1");
                    /*returnMap.put("FStockId", new VtuzxMap("FNumber", stockNo));*/
                    /*if(CP_WAREHOUSECODE.contains(stockNo)){
                        returnMap.put("FStockId", new VtuzxMap("FNumber", "001"));
                    } else{
                        returnMap.put("FStockId", new VtuzxMap("FNumber", "002"));
                    }*/
                    //20251014生产成品“委外库”
                    returnMap.put("FStockId", new VtuzxMap("FNumber", "002"));
                    returnMap.put("FLot", new VtuzxMap("FNumber", fFlot));
                    returnMap.put("FReserveType", "1");
                    returnMap.put("FBASESTOCKQTY", totalCount);
                    returnMap.put("FStockAppQty", totalCount);
                    returnMap.put("FStockQty", totalCount);
                    returnMap.put("FBaseAppQty", totalCount);
                    returnMap.put("FBaseQty", totalCount);
                    fReturnEntry.add(returnMap);
                    //标记这些明细为已处理
                    returnOrderMap.remove(key);
                }
            }
        }
        //处理剩余未匹配的退料明细
        for (List<Document> remainingOrders : returnOrderMap.values()) {
            if (!remainingOrders.isEmpty()) {
                _logger.info("发现未匹配的退料明细: " + remainingOrders.size() + "条");
            }
        }
        Map<String, Object> prdReturnOrderModel = new LinkedHashMap<>();
        Map<String, Object> prdReturnOrderParam = new LinkedHashMap<>();
        prdReturnOrderModel.put("FID", fid);
        if (!VtuzxUtil.isEmpty(returnTime) && !"Invalid Date".equals(returnTime)) {
            prdReturnOrderModel.put("FDate", returnTime);
        } else {
            prdReturnOrderModel.put("FDate", createTime);
        }
        /*20251015===日期*/
        /*prdReturnOrderModel.put("FDate", VtuzxUtil.formatYmdHmsF(new Date()));*/
        prdReturnOrderModel.put("F_sctld_ZTTLR", createUserName);
        prdReturnOrderModel.put("F_sctld_ZTDJH", billNo);
        prdReturnOrderModel.put("F_sctld_SJLY", source);
        prdReturnOrderModel.put("F_sctld_ZTTLSJ ", createTime);
        prdReturnOrderModel.put("FPrdOrgId ", "200");
        prdReturnOrderModel.put("FStockOrgId ", "200");
        prdReturnOrderModel.put("FEntity", fReturnEntry);
        prdReturnOrderParam.put("NeedUpDateFields", new ArrayList<>());
        prdReturnOrderParam.put("NeedReturnFields", new ArrayList<>());
        prdReturnOrderModel.put("IsDeleteEntry", true);
        prdReturnOrderParam.put("SubSystemId", "");
        prdReturnOrderParam.put("IsVerifyBaseDataField", false);
        prdReturnOrderParam.put("IsEntryBatchFill", true);
        prdReturnOrderParam.put("ValidateFlag", true);
        prdReturnOrderParam.put("NumberSearch", true);
        prdReturnOrderParam.put("InterationFlags", "");
        prdReturnOrderParam.put("Model", prdReturnOrderModel);
        param.append("PRD_ReturnMtrl", prdReturnOrderParam);
        try {
            List<VtuzxMap> prdReturnBillList = kingdeeService.save(client, "PRD_ReturnMtrl", prdReturnOrderParam);
            VtuzxMap prdReturnMap = prdReturnBillList.get(0);
            String number = VtuzxUtil.getString(prdReturnMap, "Number");
            kingdeeService.submit(client, "PRD_ReturnMtrl", "0", number);
            kingdeeService.audit(client, "PRD_ReturnMtrl", "0", number, "STK_InvCheckResult");
            historyDoc.append("kingdeeNumber", number);
            historyDoc.append("prdReturnOrder", true);
        } catch (Exception e) {
            _logger.info(e.getMessage());
            throw e;
        }
    }
}
